基于SpringSecurity的动态授权
第一步:创建数据库

第二步:运行SQL文件
SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;
DROP TABLE IF EXISTS `menu`;
CREATE TABLE `menu` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`pattern` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL,
PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 5 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Compact;
INSERT INTO `menu` VALUES (1, '/db/**');
INSERT INTO `menu` VALUES (2, '/admin/**');
INSERT INTO `menu` VALUES (3, '/user/**');
DROP TABLE IF EXISTS `menu_role`;
CREATE TABLE `menu_role` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`mid` int(11) NOT NULL,
`rid` int(11) NOT NULL,
PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 7 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Compact;
INSERT INTO `menu_role` VALUES (1, 1, 1);
INSERT INTO `menu_role` VALUES (2, 2, 2);
INSERT INTO `menu_role` VALUES (3, 3, 3);
DROP TABLE IF EXISTS `role`;
CREATE TABLE `role` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL,
`nameZh` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL,
PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 4 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Compact;
INSERT INTO `role` VALUES (1, 'ROLE_dba', '数据库管理员');
INSERT INTO `role` VALUES (2, 'ROLE_admin', '系统管理员');
INSERT INTO `role` VALUES (3, 'ROLE_user', '用户');
DROP TABLE IF EXISTS `user`;
CREATE TABLE `user` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`username` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL,
`password` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL,
`enabled` tinyint(1) NOT NULL DEFAULT 1,
`locked` tinyint(1) NOT NULL DEFAULT 0,
PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 4 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Compact;
INSERT INTO `user` VALUES (1, 'root', '123', 0, 0);
INSERT INTO `user` VALUES (2, 'admin', '123', 0, 0);
INSERT INTO `user` VALUES (3, 'user', '123', 0, 0);
DROP TABLE IF EXISTS `user_role`;
CREATE TABLE `user_role` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`uid` int(11) NOT NULL,
`rid` int(11) NOT NULL,
PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 7 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Compact;
INSERT INTO `user_role` VALUES (1, 1, 1);
INSERT INTO `user_role` VALUES (2, 1, 2);
INSERT INTO `user_role` VALUES (3, 1, 3);
INSERT INTO `user_role` VALUES (4, 2, 2);
INSERT INTO `user_role` VALUES (5, 2, 3);
INSERT INTO `user_role` VALUES (6, 3, 3);
SET FOREIGN_KEY_CHECKS = 1;
第三步: 创建项目导入依赖
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>2.1.3</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.70</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt</artifactId>
<version>0.9.0</version>
</dependency>
</dependencies>
第四步: 配置文件
server.port=9090
server.tomcat.uri-encoding=UTF-8
spring.application.name=security_demo
spring.datasource.url=jdbc:mysql://127.0.0.1:3306/spring-security?useUnicode=true&characterEncoding=utf8&serverTimezone=CTT
spring.datasource.username=root
spring.datasource.password=123456
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
mybatis.mapper-locations=classpath:mapper/*.xml
logging.level.com.xiaohei=debug
第五步: 创建实体类
package com.xiaohei.security_demo.entity;
public class LoginUser {
private String username;
private String password;
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
}
package com.xiaohei.security_demo.entity;
import java.io.Serializable;
import java.util.List;
public class Menu implements Serializable {
private Integer id;
private String pattern;
private List<Role> roles;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getPattern() {
return pattern;
}
public void setPattern(String pattern) {
this.pattern = pattern;
}
public List<Role> getRoles() {
return roles;
}
public void setRoles(List<Role> roles) {
this.roles = roles;
}
}
package com.xiaohei.security_demo.entity;
import java.io.Serializable;
public class Role implements Serializable {
private Integer id;
private String name;
private String nameZh;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getNameZh() {
return nameZh;
}
public void setNameZh(String nameZh) {
this.nameZh = nameZh;
}
}
package com.xiaohei.security_demo.entity;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
public class User implements Serializable, UserDetails {
private static final Logger log = LoggerFactory.getLogger(User.class);
private Integer id;
private String username;
private String password;
private Boolean enabled;
private Boolean locked;
private List<Role> roles;
public Integer getId() {
return id;
}
@Override
public Collection<? extends GrantedAuthority> getAuthorities() {
System.out.println("-------> User.getAuthorities()");
List<SimpleGrantedAuthority> authority = new ArrayList<>();
for (Role role : this.roles) {
authority.add(new SimpleGrantedAuthority(role.getName()));
}
return authority;
}
@Override
public String getPassword() {
return this.password;
}
@Override
public String getUsername() {
return this.username;
}
public Boolean getEnabled() {
return enabled;
}
public void setEnabled(Boolean enabled) {
this.enabled = enabled;
}
public Boolean getLocked() {
return locked;
}
public void setLocked(Boolean locked) {
this.locked = locked;
}
@Override
public boolean isAccountNonExpired() {
return true;
}
public void setId(Integer id) {
this.id = id;
}
public void setUsername(String username) {
this.username = username;
}
public void setPassword(String password) {
this.password = password;
}
public List<Role> getRoles() {
return roles;
}
public void setRoles(List<Role> roles) {
this.roles = roles;
}
@Override
public boolean isAccountNonLocked() {
return true;
}
@Override
public boolean isCredentialsNonExpired() {
return !this.getLocked();
}
@Override
public boolean isEnabled() {
return !this.getEnabled();
}
@Override
public String toString() {
return "User{" +
"id=" + id +
", username='" + username + '\'' +
", password='" + password + '\'' +
", enabled=" + enabled +
", locked=" + locked +
", roles=" + roles +
'}';
}
}
package com.xiaohei.security_demo.util;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.ExpiredJwtException;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import java.util.Date;
public class TokenUtils {
public static final String TOKEN_HEADER = "Authorization";
public static final String TOKEN_PREFIX = "Bearer ";
private static final String SECRET = "xiaohei";
private static final String ISS = "echisan";
private static final String ROLE_CLAIMS = "rol";
private static final long EXPIRATION = 3600L;
private static final long EXPIRATION_REMEMBER = 604800L;
public static String createToken(String username) {
return Jwts.builder()
.signWith(SignatureAlgorithm.HS512, SECRET)
.setIssuer(ISS)
.setSubject(username)
.setIssuedAt(new Date())
.setExpiration(new Date(System.currentTimeMillis() * 1000))
.compact();
}
public static String getUsername(String token){
return getTokenBody(token).getSubject();
}
public static boolean isExpiration(String token){
try{
return getTokenBody(token).getExpiration().before(new Date());
}catch (ExpiredJwtException e){
return true;
}
}
public static Claims getTokenBody(String token){
return Jwts.parser()
.setSigningKey(SECRET)
.parseClaimsJws(token)
.getBody();
}
}
第六步: 创建mapper与dao
package com.xiaohei.security_demo.dao;
import com.xiaohei.security_demo.entity.Menu;
import org.apache.ibatis.annotations.Mapper;
import java.util.List;
@Mapper
public interface MenuMapper {
List<Menu> getAllMenus();
}
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.xiaohei.security_demo.dao.MenuMapper">
<resultMap id="baseResultMap" type="com.xiaohei.security_demo.entity.Menu">
<id property="id" column="id"/>
<result property="pattern" column="pattern"/>
<collection property="roles" ofType="com.xiaohei.security_demo.entity.Role">
<id property="id" column="rid"/>
<result property="name" column="rname"/>
<result property="nameZh" column="rnameZh"/>
</collection>
</resultMap>
<select id="getAllMenus" resultMap="baseResultMap">
select m.id, m.pattern, r.id as rid, r.name as rname, r.nameZh as rnameZh
from menu m
left join menu_role mr on m.id = mr.mid
left join role r on mr.rid = r.id;
</select>
</mapper>
package com.xiaohei.security_demo.dao;
import com.xiaohei.security_demo.entity.Role;
import com.xiaohei.security_demo.entity.User;
import org.apache.ibatis.annotations.Mapper;
import java.util.List;
@Mapper
public interface UserMapper {
User loadUserByUsername(String username);
List<Role> getUserRolesByUid(Integer id);
User login(String username, String password);
}
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.xiaohei.security_demo.dao.UserMapper">
<select id="loadUserByUsername" resultType="com.xiaohei.security_demo.entity.User"
parameterType="java.lang.String">
select * from user where username=#{username}
</select>
<select id="getUserRolesByUid" parameterType="java.lang.Integer"
resultType="com.xiaohei.security_demo.entity.Role">
select r.id,r.name,r.nameZh from role r,user_role ur where r.id=ur.rid and ur.uid=#{id}
</select>
<select id="login" parameterType="java.lang.String" resultType="com.xiaohei.security_demo.entity.User">
select * from user where username=#{username} and password=#{password}
</select>
</mapper>
package com.xiaohei.security_demo.service.impl;
import com.alibaba.fastjson.JSON;
import com.xiaohei.security_demo.dao.UserMapper;
import com.xiaohei.security_demo.entity.User;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Component;
@Component
public class UserServiceImpl implements UserDetailsService {
private static final Logger LOG = LoggerFactory.getLogger(UserServiceImpl.class);
@Autowired
private UserMapper userMapper;
@Autowired
private PasswordEncoder passwordEncoder;
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
System.out.println("------------------------> UserService.loadUserByUsername()");
User user = userMapper.loadUserByUsername(username);
if (user == null){
throw new UsernameNotFoundException("用户不存在");
}
user.setRoles(userMapper.getUserRolesByUid(user.getId()));
System.out.println("----- user ------>"+ JSON.toJSONString(user));
user.setPassword(passwordEncoder.encode(user.getPassword()));
return user;
}
}
第七步:实现FilterInvocationSecurityMetadataSource
package com.xiaohei.security_demo.filter;
import com.alibaba.fastjson.JSON;
import com.xiaohei.security_demo.dao.MenuMapper;
import com.xiaohei.security_demo.entity.Menu;
import com.xiaohei.security_demo.entity.Role;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.ConfigAttribute;
import org.springframework.security.access.SecurityConfig;
import org.springframework.security.web.FilterInvocation;
import org.springframework.security.web.access.intercept.FilterInvocationSecurityMetadataSource;
import org.springframework.stereotype.Component;
import org.springframework.util.AntPathMatcher;
import javax.annotation.PostConstruct;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
@Component
public class CustomerFilterInvocationSecurityMetadataSource implements FilterInvocationSecurityMetadataSource {
@Autowired
private MenuMapper menuMapper;
private static final Logger log = LoggerFactory.getLogger(CustomerFilterInvocationSecurityMetadataSource.class);
private static List<Menu> allMenus = null;
@PostConstruct
private void getMenus(){
System.out.println(" ------------ menuMapper -------->"+menuMapper);
allMenus = menuMapper.getAllMenus();
System.out.println(" ------------ allMenus ----------> \n"+ JSON.toJSONString(allMenus));
}
@Override
public Collection<ConfigAttribute> getAttributes(Object object) throws IllegalArgumentException {
AntPathMatcher antPathMatcher = new AntPathMatcher();
System.out.println("*********************************************************");
System.out.println("---------------------> getAttributes ------------------->");
String [] roleAll = new String[]{};
String url = ((FilterInvocation)object).getRequestUrl();
System.out.println("----------> url --------->"+ url);
for (Menu menu : allMenus) {
if (antPathMatcher.match(menu.getPattern(),url)){
List<Role> roles = menu.getRoles();
roleAll = new String[roles.size()];
for (int i = 0; i < roleAll.length; i++) {
roleAll[i] = roles.get(i).getName();
}
}
}
return SecurityConfig.createList(roleAll);
}
@Override
public Collection<ConfigAttribute> getAllConfigAttributes() {
System.out.println("-----------------getAllConfigAttributes-----------");
return null;
}
@Override
public boolean supports(Class<?> clazz) {
System.out.println("-----------------supports-----------");
return true;
}
}
第八步: 实现AccessDecisionManager
package com.xiaohei.security_demo.filter;
import com.alibaba.fastjson.JSON;
import org.springframework.security.access.AccessDecisionManager;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.security.access.ConfigAttribute;
import org.springframework.security.authentication.InsufficientAuthenticationException;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.stereotype.Component;
import java.util.Collection;
public class CustomerAccessDecisionManger implements AccessDecisionManager {
@Override
public void decide(Authentication authentication, Object object, Collection<ConfigAttribute> configAttributes) throws AccessDeniedException, InsufficientAuthenticationException {
if (configAttributes.size() == 0) {
return;
}
System.out.println(" -------------> AccessDecisionManager.decide------>");
Collection<? extends GrantedAuthority> auths = authentication.getAuthorities();
for (ConfigAttribute configAttribute : configAttributes) {
System.out.println("-----url_role_required-----> " + configAttribute.getAttribute());
System.out.println("-----auths-----> " + JSON.toJSONString(auths));
String attribute = configAttribute.getAttribute();
for (GrantedAuthority auth : auths) {
if (attribute.trim().equals(auth.getAuthority())){
return;
}
}
}
throw new AccessDeniedException("抱歉,您没有访问权限");
}
@Override
public boolean supports(ConfigAttribute attribute) {
return true;
}
@Override
public boolean supports(Class<?> clazz) {
return true;
}
}
第八步: OncePerRequestFilter
package com.xiaohei.security_demo.filter;
import com.xiaohei.security_demo.entity.User;
import com.xiaohei.security_demo.util.TokenUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.web.authentication.WebAuthenticationDetailsSource;
import org.springframework.security.web.authentication.www.BasicAuthenticationFilter;
import org.springframework.web.filter.OncePerRequestFilter;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
public class JwtAuthenticationTokenFilter extends OncePerRequestFilter {
@Autowired(required = false)
private UserDetailsService userDetailsService;
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
String token = request.getHeader(TokenUtils.TOKEN_HEADER);
if (token!=null && !token.equals("")){
token = token.replace(TokenUtils.TOKEN_PREFIX, "");
System.out.println(userDetailsService);
String username = TokenUtils.getUsername(token);
System.out.println(username);
UserDetails userDetails = this.userDetailsService.loadUserByUsername(username);
UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities());
authentication.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
SecurityContextHolder.getContext().setAuthentication(authentication);
}
filterChain.doFilter(request,response);
}
}
第九步: 编写自定义的Exception
package com.xiaohei.security_demo.exception;
import com.alibaba.fastjson.JSON;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.AuthenticationEntryPoint;
import org.springframework.stereotype.Component;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
@Component
public class RestAuthenticationEntryPoint implements AuthenticationEntryPoint {
@Override
public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException authException) throws IOException, ServletException, IOException {
response.setCharacterEncoding("UTF-8");
response.setContentType("application/json");
response.getWriter().println(JSON.toJSONString(authException.getMessage()));
response.getWriter().flush();
}
}
package com.xiaohei.security_demo.exception;
import com.alibaba.fastjson.JSON;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.security.web.access.AccessDeniedHandler;
import org.springframework.stereotype.Component;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
@Component
public class RestfulAccessDeniedHandler implements AccessDeniedHandler {
@Override
public void handle(HttpServletRequest request,
HttpServletResponse response,
AccessDeniedException e) throws IOException, ServletException {
response.setCharacterEncoding("UTF-8");
response.setContentType("application/json");
response.getWriter().println(JSON.toJSONString(e.getMessage()));
response.getWriter().flush();
}
}
第十步: 编写SpringSecurity的Config文件
package com.xiaohei.security_demo.config;
import com.xiaohei.security_demo.exception.RestAuthenticationEntryPoint;
import com.xiaohei.security_demo.exception.RestfulAccessDeniedHandler;
import com.xiaohei.security_demo.filter.CustomerAccessDecisionManger;
import com.xiaohei.security_demo.filter.CustomerFilterInvocationSecurityMetadataSource;
import com.xiaohei.security_demo.filter.JWTAuthorizationTokenFilter;
import com.xiaohei.security_demo.filter.JwtAuthenticationTokenFilter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.context.annotation.Bean;
import org.springframework.http.HttpMethod;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.config.annotation.ObjectPostProcessor;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.builders.WebSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.access.intercept.FilterSecurityInterceptor;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Qualifier("userServiceImpl")
@Autowired(required = false)
private UserDetailsService userDetailsService;
@Autowired
private RestfulAccessDeniedHandler restfulAccessDeniedHandler;
@Autowired
private RestAuthenticationEntryPoint restAuthenticationEntryPoint;
@Autowired
private CustomerFilterInvocationSecurityMetadataSource customerFilterInvocationSecurityMetadataSource;
@Bean
public PasswordEncoder passwordEncoder() {
System.out.println("----------------> MyWebSecurityConfig.passwordEncoder()");
return new BCryptPasswordEncoder(15);
}
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userDetailsService)
.passwordEncoder(passwordEncoder());
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http.cors().and().csrf().disable()
.authorizeRequests()
.withObjectPostProcessor(new ObjectPostProcessor<FilterSecurityInterceptor>() {
@Override
public <O extends FilterSecurityInterceptor> O postProcess(O object) {
object.setSecurityMetadataSource(customerFilterInvocationSecurityMetadataSource);
object.setAccessDecisionManager(new CustomerAccessDecisionManger());
return object;
}
})
.and()
.authorizeRequests()
.antMatchers(HttpMethod.GET,
"/",
"/*.html",
"/favicon.ico",
"/**/*.html",
"/**/*.css",
"/**/*.js",
"/swagger-resources/**",
"/v2/api-docs/**"
)
.permitAll()
.antMatchers("/auth/login", "/admin/register")
.permitAll()
.antMatchers(HttpMethod.OPTIONS)
.permitAll()
.anyRequest()
.authenticated()
.and()
.httpBasic().and()
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
.and()
.exceptionHandling();
http.addFilterBefore(jwtAuthenticationTokenFilter(), UsernamePasswordAuthenticationFilter.class);
http.exceptionHandling()
.accessDeniedHandler(restfulAccessDeniedHandler)
.authenticationEntryPoint(restAuthenticationEntryPoint);
}
@Override
public void configure(WebSecurity web) throws Exception {
web.ignoring().antMatchers("/api/**");
}
@Bean
public JwtAuthenticationTokenFilter jwtAuthenticationTokenFilter(){
return new JwtAuthenticationTokenFilter();
}
}
package com.xiaohei.security_demo.config;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Configuration
public class WebMvcConfig implements WebMvcConfigurer {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**")
.allowedOrigins("*")
.allowCredentials(true)
.allowedMethods("*")
.maxAge(3600);
}
}
第十一步: 最激动人心的Controller文件
package com.xiaohei.security_demo.controller;
import com.xiaohei.security_demo.dao.UserMapper;
import com.xiaohei.security_demo.entity.LoginUser;
import com.xiaohei.security_demo.entity.User;
import com.xiaohei.security_demo.util.TokenUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.web.bind.annotation.*;
import java.util.HashMap;
import java.util.Map;
@RestController
@CrossOrigin
public class TestSecurityController {
@Autowired
UserMapper userMapper;
@GetMapping("/admin/xiaohei")
public String getAll(){
return "我是大帝";
}
@GetMapping("/api/xiaohie")
public String getNoAll(){
return "我是小弟";
}
@PostMapping("/user/user")
public String getXiaohei(){
return "我是xiaohei";
}
@PostMapping("/auth/login")
public Map<String,String> login(@RequestBody LoginUser login){
System.out.println(this.passwordEncoder);
System.out.println(login.getUsername());
System.out.println(passwordEncoder.encode(login.getPassword()));
User user = userMapper.login(login.getUsername(),login.getPassword());
Map<String,String> map = new HashMap<String,String>();
if (user == null){
map.put("201","用户名或者密码错误");
return map;
}
String token = TokenUtils.createToken(user.getUsername());
map.put("token",token);
map.put("tokenHead",TokenUtils.TOKEN_PREFIX);
return map;
}
}
最后: 你们可能最想要的前端代码,哈哈哈
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>图片上传</title>
<!-- 引入样式文件 -->
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/vant@2.12/lib/index.css" />
<!-- 引入 Vue 和 Vant 的 JS 文件 -->
<script src="https://cdn.jsdelivr.net/npm/vue@2.6/dist/vue.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/vant@2.12/lib/vant.min.js"></script>
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
<style>
</style>
</head>
<body>
<div id="app">
<van-form @submit="onSubmit">
<div>
<van-field v-model="username" name="username" label="用户名" placeholder="用户名"
:rules="[{ required: true, message: '请填写用户名' }]" />
</div>
<div>
<van-field v-model="password" type="password" name="password" label="密码" placeholder="密码"
:rules="[{ required: true, message: '请填写密码' }]" />
</div>
<div style="margin: 16px;">
<van-button round block type="info" native-type="submit">提交</van-button>
</div>
</van-form>
<button @click="api">admin权限请求</button>
<button @click="xiaohei">xiaohei权限请求</button>
</div>
<script>
new Vue({
el: '#app',
data() {
return {
username: '',
password: '',
token: ''
}
},
mounted() {
axios.defaults.withCredentials = true;
},
methods: {
onSubmit(values) {
console.log(values);
axios.post("http://localhost:9090/auth/login", {
"username": values.username,
"password": values.password
}).then(res => {
stoken = res.data.token;
tokenHead=res.data.tokenHead;
console.log(res);
this.token = tokenHead+stoken;
console.log(this.token);
})
},
api() {
axios({
headers:{
'authorization':this.token
},
method:'get',
url:'http://localhost:9090/admin/xiaohei'
}).then(res =>{
console.log(res);
})
},
xiaohei(){
axios({
headers:{
'authorization':this.token
},
method:'post',
url:'http://localhost:9090/user/user'
}).then(res =>{
console.log(res);
})
}
}
});
Vue.use(vant.Form);
</script>
</body>
</html>