当前位置:   article > 正文

spring security 认证授权详解_spring security认证和授权流程

spring security认证和授权流程

spring security简介

Spring Security 是 Spring家族中的一个安全管理框架,它提供了更丰富的功能做认证授权

  • 认证:当前用户有没有权限登录,是否为本系统用户
  • 授权:当前登录的用户有没有操作功能的权限

spring security的搭建

引入依赖

  1. <dependencies>
  2. <dependency>
  3. <groupId>cn.hutool</groupId>
  4. <artifactId>hutool-all</artifactId>
  5. <version>5.5.2</version>
  6. </dependency>
  7. <dependency>
  8. <groupId>com.auth0</groupId>
  9. <artifactId>java-jwt</artifactId>
  10. <version>3.10.3</version>
  11. </dependency>
  12. <dependency>
  13. <groupId>org.springframework.boot</groupId>
  14. <artifactId>spring-boot-starter-data-redis</artifactId>
  15. </dependency>
  16. <dependency>
  17. <groupId>org.springframework.boot</groupId>
  18. <artifactId>spring-boot-starter-security</artifactId>
  19. </dependency>
  20. <dependency>
  21. <groupId>com.baomidou</groupId>
  22. <artifactId>mybatis-plus-boot-starter</artifactId>
  23. <version>3.4.0</version>
  24. </dependency>
  25. <dependency>
  26. <groupId>com.mysql</groupId>
  27. <artifactId>mysql-connector-j</artifactId>
  28. <scope>runtime</scope>
  29. </dependency>
  30. <dependency>
  31. <groupId>com.alibaba</groupId>
  32. <artifactId>fastjson</artifactId>
  33. <version>1.2.75</version>
  34. </dependency>
  35. <dependency>
  36. <groupId>org.springframework.boot</groupId>
  37. <artifactId>spring-boot-starter-web</artifactId>
  38. </dependency>
  39. <dependency>
  40. <groupId>org.projectlombok</groupId>
  41. <artifactId>lombok</artifactId>
  42. <optional>true</optional>
  43. </dependency>
  44. <dependency>
  45. <groupId>org.springframework.boot</groupId>
  46. <artifactId>spring-boot-starter-test</artifactId>
  47. <scope>test</scope>
  48. </dependency>
  49. <dependency>
  50. <groupId>org.springframework.security</groupId>
  51. <artifactId>spring-security-test</artifactId>
  52. <scope>test</scope>
  53. </dependency>
  54. </dependencies>

 创建数据库表

  1. create table user
  2. (
  3. password varchar(100) null,
  4. username varchar(50) null,
  5. id varchar(50) not null
  6. primary key
  7. )
  8. comment '用户表';

项目配置如下

  1. server:
  2. port: 9000
  3. spring:
  4. datasource:
  5. url: jdbc:mysql://xxxx:3306/security_db?useSSL=true&serverTimezone=Asia/Shanghai
  6. username: root
  7. password: root123456
  8. driver-class-name: com.mysql.cj.jdbc.Driver
  9. redis:
  10. cluster:
  11. nodes:
  12. - 39.106.53.30:6379
  13. - 39.106.53.30:6380
  14. - 39.106.53.30:6381
  15. - 39.106.53.30:6382
  16. - 39.106.53.30:6383
  17. - 39.106.53.30:6384
  18. mybatis-plus:
  19. mapper-locations: classpath:/mapper/*.xml
  20. type-aliases-package: com.tech.security.securityservice.model

直接访问接口

没有经过认证的接口都会进入spring security的默认登录界面

spring security的原理

SpringSecurity的原理其实就是一个过滤器链,内部包含了提供各种功能的过滤器

主要的过滤器如下

  • UsernamePasswordAuthenticationFilter:负责处理我们在登陆页面填写了用户名密码后的登陆请求。入门案例的认证工作主要有它负责。
  • ExceptionTranslationFilter:处理过滤器链中抛出的任何AccessDeniedException和AuthenticationException。
  • FilterSecurityInterceptor:负责权限校验的过滤器

 可以看到,在spring 容器中就有spring security的过滤器链,包括熟悉的过滤器UsernamePasswordAuthenticationFilter、FilterSecurityInterceptor等过滤器

spring security认证

认证流程

Authentication接口: 它的实现类,表示当前访问系统的用户,封装了用户相关信息。
AuthenticationManager接口:定义了认证Authentication的方法
UserDetailsService接口:加载用户特定数据的核心接口。里面定义了一个根据用户名查询用户信息的方法
UserDetails接口:提供核心用户信息。通过UserDetailsService根据用户名获取处理的用户信息要封装成UserDetails对象返回,然后将这些信息封装到Authentication对象中

UsernamePasswordAuthenticationFilter实现类:实现了我们最常用的基于用户名和密码的认证逻辑,封装Authentication对象
DaoAuthenticationProvider实现类:是AuthenticationManager中管理的其中一个Provider,因为是要访问数据库

定义jwt认证工具类

我这里采用的是java-jwt,可能和jj-jwt写法和解析方式有所不同

  1. /**
  2. * @author sl
  3. */
  4. @Slf4j
  5. public class JwtTokenUtils {
  6. /**
  7. * 额外的数据,越复杂越安全
  8. */
  9. private static final String SING_VALUE = "dsdadfsghkjlsdfnmkjsd";
  10. /**
  11. * 过期时间
  12. */
  13. private static ReactiveRedisOperations<Object, Object> redisTemplate;
  14. public static String getJwtToken(String id){
  15. String JwtToken = JWT.create()
  16. .withClaim("userId",id)
  17. .withExpiresAt(DateUtil.offsetHour(new Date(),1))
  18. .sign(Algorithm.HMAC256(SING_VALUE));
  19. return JwtToken;
  20. }
  21. public static boolean CheckToken(String token){
  22. try {
  23. JWT.require(Algorithm.HMAC256(SING_VALUE)).build().verify(token);
  24. return true;
  25. } catch (Exception exception) {
  26. return false;
  27. }
  28. }
  29. public static String parseTokenInfo(String token){
  30. DecodedJWT verify = JWT.require(Algorithm.HMAC256(SING_VALUE)).build().verify(token);
  31. Claim claim = verify.getClaim("userId");
  32. return claim.asString();
  33. }
  34. }

定义userDetails实现类

  1. @Data
  2. public class LoginUser implements UserDetails {
  3. private String id;
  4. private String username;
  5. private String password;
  6. private String token;
  7. private String authority;
  8. @Override
  9. public Collection<? extends GrantedAuthority> getAuthorities() {return null;}
  10. @Override
  11. public boolean isAccountNonExpired() {
  12. return true;
  13. }
  14. @Override
  15. public boolean isAccountNonLocked() {
  16. return true;
  17. }
  18. @Override
  19. public boolean isCredentialsNonExpired() {
  20. return true;
  21. }
  22. @Override
  23. public boolean isEnabled() {
  24. return true;
  25. }
  26. }

 定义UserDetailsService实现类

目的是去数据库中查询用户信息,并返回UserDetails对象

  1. /**
  2. * @author sl
  3. */
  4. @Service
  5. public class SecurityUserDetailServiceImpl implements UserDetailsService {
  6. @Autowired
  7. private UserMapper userMapper;
  8. @Override
  9. public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
  10. QueryWrapper<User> userQueryWrapper = new QueryWrapper<>();
  11. userQueryWrapper.eq("username",username);
  12. User user = userMapper.selectOne(userQueryWrapper);;
  13. if(Objects.isNull(user)){
  14. throw new RuntimeException("用户名或密码错误");
  15. }
  16. //TODO 根据用户查询权限信息 添加到LoginUser中
  17. LoginUser loginUser = new LoginUser();
  18. loginUser.setId(user.getId());
  19. loginUser.setUsername(user.getUsername());
  20. loginUser.setPassword(new BCryptPasswordEncoder().encode(user.getPassword()));
  21. loginUser.setAuthority("");
  22. return loginUser;
  23. }
  24. }

登录以及退出登录

通过认证器进入登录认证流程,退出认证直接删除redis缓存即可

  1. @Service
  2. public class UserServiceImpl implements UserService {
  3. @Autowired
  4. private StringRedisTemplate redisTemplate;
  5. /**
  6. * 认证器
  7. */
  8. @Autowired
  9. private AuthenticationManager authenticationManager;
  10. @Override
  11. public LoginUser login(LoginUser user) {
  12. // 使用security认证
  13. UsernamePasswordAuthenticationToken usernamePasswordAuthenticationToken = new UsernamePasswordAuthenticationToken(user.getUsername(), user.getPassword());
  14. Authentication authenticate = authenticationManager.authenticate(usernamePasswordAuthenticationToken);
  15. LoginUser principal = (LoginUser) authenticate.getPrincipal();
  16. if (authenticate.isAuthenticated()) {
  17. String jwtToken = JwtTokenUtils.getJwtToken(principal.getId());
  18. redisTemplate.opsForValue().set("login_"+principal.getId(), JSON.toJSONString(principal) ,1,TimeUnit.DAYS);
  19. principal.setToken(jwtToken);
  20. }
  21. return principal;
  22. }
  23. @Override
  24. public void logout() {
  25. Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
  26. LoginUser loginUser = (LoginUser) authentication.getPrincipal();
  27. redisTemplate.delete("login:"+loginUser.getId());
  28. }
  29. }

配置自定义认证过滤器进行jwt认证

主要是解析请求头中包含的token信息,并存入SecurityContextHolder上下文中

  1. /**
  2. * @author Administrator
  3. */
  4. @Component
  5. public class JwtAuthenticationTokenFilter extends OncePerRequestFilter {
  6. @Autowired
  7. private StringRedisTemplate redisTemplate;
  8. @Override
  9. protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
  10. //获取token
  11. String token = request.getHeader("token");
  12. String loginUserString = null;
  13. try {
  14. if (!StringUtils.hasText(token)) {
  15. //放行
  16. filterChain.doFilter(request, response);
  17. return;
  18. }
  19. if(token !=null){
  20. String userId= JwtTokenUtils.parseTokenInfo(token);
  21. loginUserString= redisTemplate.opsForValue().get("login_" + userId);
  22. }
  23. }catch (Exception e) {
  24. throw new RuntimeException("用户未登录");
  25. }
  26. LoginUser loginUser = JSON.parseObject(loginUserString, LoginUser.class);
  27. UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(loginUser,null,null);
  28. SecurityContextHolder.getContext().setAuthentication(authenticationToken);
  29. filterChain.doFilter(request, response);
  30. }
  31. }

 将jwt认证过滤器加入过滤器链中

  1. /**
  2. * @author sl
  3. */
  4. @EnableWebSecurity
  5. @Configuration
  6. public class SecurityConfig {
  7. @Autowired
  8. private JwtAuthenticationTokenFilter jwtAuthenticationTokenFilter;
  9. @Bean
  10. public PasswordEncoder passwordEncoder(){
  11. return new BCryptPasswordEncoder();
  12. }
  13. @Bean
  14. public AuthenticationManager authenticationManager(AuthenticationConfiguration authenticationConfiguration) throws Exception {
  15. return authenticationConfiguration.getAuthenticationManager();
  16. }
  17. @Bean
  18. public SecurityFilterChain securityFilterChain(HttpSecurity httpSecurity) throws Exception {
  19. httpSecurity.csrf().disable();
  20. httpSecurity.authorizeRequests()
  21. .antMatchers("/user/login").anonymous()
  22. .anyRequest().authenticated()
  23. .and()
  24. .formLogin();
  25. // 在UsernamePasswordAuthenticationFilter之前添加自定义token前置过滤器
  26. httpSecurity.addFilterBefore(jwtAuthenticationTokenFilter, UsernamePasswordAuthenticationFilter.class);
  27. return httpSecurity.build();
  28. }
  29. }

测试认证

直接访问登录接口,传递用户名密码进入认证流程, 返回token

携带token访问,认证成功

spring security授权 

授权的概念:当前登录的用户有没有操作功能的权限

授权的模型:rbac(Role-Based Access Control)模型

授权方式:注解,配置

rbac授权模型

基于角色的权限控制。这是目前最常被开发者使用也是相对易用、通用权限模型

数据库脚本 

共5张表结构,用户表,角色表,权限表,用户角色表,用户权限表

  1. create table perm
  2. (
  3. id varchar(60) not null
  4. primary key,
  5. func_name varchar(64) default 'NULL' not null comment '功能名称',
  6. path varchar(200) null comment '路由地址',
  7. status char default '0' null comment '功能状态(0正常 1停用)',
  8. perms varchar(100) null comment '权限标识',
  9. create_time datetime null,
  10. update_time datetime null,
  11. del_flag int default 0 null comment '是否删除(0未删除 1已删除)',
  12. remark varchar(500) null comment '备注'
  13. )
  14. comment '权限表';
  15. INSERT INTO perm (id, func_name, path, status, perms, create_time, update_time, del_flag, remark) VALUES ('dfasdfgfdg', '审批功能', '/audit', '0', 'audit', '2023-10-11 15:20:16', '2023-10-11 15:20:18', 0, '审批功能');
  16. INSERT INTO perm (id, func_name, path, status, perms, create_time, update_time, del_flag, remark) VALUES ('fdsfdsfhgfsjy', '删除功能', '/delete', '0', 'delete', '2023-10-11 11:26:58', '2023-10-11 11:27:02', 0, '删除权限');
  17. create table user
  18. (
  19. id varchar(50) not null
  20. primary key,
  21. username varchar(50) null,
  22. password varchar(100) null
  23. )
  24. comment '用户表';
  25. INSERT INTO user (id, username, password) VALUES ('qwertreyt', 'ceshi', 'ceshi');
  26. INSERT INTO user (id, username, password) VALUES ('sdafasf214', 'admin', 'admin');
  27. create table role
  28. (
  29. id varchar(60) not null
  30. primary key,
  31. name varchar(128) null,
  32. role_key varchar(100) null comment '角色权限字符串',
  33. status char default '0' null comment '角色状态(0正常 1停用)',
  34. del_flag int default 0 null comment 'del_flag',
  35. create_time datetime null,
  36. update_time datetime null,
  37. remark varchar(500) null comment '备注'
  38. )
  39. comment '角色表';
  40. INSERT INTO role (id, name, role_key, status, del_flag, create_time, update_time, remark) VALUES ('qwerqwerer', '管理员', 'amdin', '0', 0, '2023-10-11 11:22:00', '2023-10-11 11:22:09', '管理员角色');
  41. INSERT INTO role (id, name, role_key, status, del_flag, create_time, update_time, remark) VALUES ('uiplpptry', '普通用户', 'ceshi1', '0', 0, '2023-10-11 15:31:39', '2023-10-11 15:31:42', '普通用户');
  42. create table role_perm
  43. (
  44. role_id varchar(60) not null comment '角色ID',
  45. perm_id varchar(60) not null comment '菜单id',
  46. primary key (role_id, perm_id)
  47. );
  48. INSERT INTO role_perm (role_id, perm_id) VALUES ('qwerqwerer', 'dfasdfgfdg');
  49. INSERT INTO role_perm (role_id, perm_id) VALUES ('qwerqwerer', 'fdsfdsfhgfsjy');
  50. INSERT INTO role_perm (role_id, perm_id) VALUES ('uiplpptry', 'fdsfdsfhgfsjy');
  51. create table user_role
  52. (
  53. user_id varchar(60) not null comment '用户id',
  54. role_id varchar(60) not null comment '角色id',
  55. primary key (user_id, role_id)
  56. );
  57. INSERT INTO user_role (user_id, role_id) VALUES ('sdafasf214', 'qwerqwerer');
  58. INSERT INTO user_role (user_id, role_id) VALUES ('qwertreyt', 'uiplpptry');

开启权限配置

@EnableGlobalMethodSecurity(prePostEnabled = true)

  1. /**
  2. * @author sl
  3. */
  4. @EnableWebSecurity
  5. @EnableGlobalMethodSecurity(prePostEnabled = true)
  6. @Configuration
  7. public class SecurityConfig {
  8. ....
  9. }

建立mapper通过用户id查询权限

  1. <?xml version="1.0" encoding="UTF-8" ?>
  2. <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
  3. <mapper namespace="com.tech.security.securityservice.mapper.PermMapper">
  4. <select id="findPermByUserId" resultType="perm">
  5. select p.*
  6. from
  7. user u left join user_role ur
  8. on ur.user_id = u.id
  9. left join role_perm rm
  10. on ur.role_id = rm.role_id
  11. left join perm p
  12. on rm.perm_id = p.id
  13. where user_id = #{userId}
  14. </select>
  15. </mapper>

将用户权限封装到userDetails对象中 

LoginUser加入权限

  1. package com.tech.security.securityservice.model;
  2. import com.alibaba.fastjson.annotation.JSONField;
  3. import lombok.Data;
  4. import org.springframework.security.core.GrantedAuthority;
  5. import org.springframework.security.core.authority.SimpleGrantedAuthority;
  6. import org.springframework.security.core.userdetails.UserDetails;
  7. import java.util.Collection;
  8. import java.util.List;
  9. import java.util.stream.Collectors;
  10. @Data
  11. public class LoginUser implements UserDetails {
  12. private String id;
  13. private String username;
  14. private String password;
  15. private String token;
  16. /**
  17. *存储权限信息
  18. */
  19. private List<String> permissions;
  20. /**
  21. *存储SpringSecurity所需要的权限信息的集合
  22. */
  23. @JSONField(serialize = false)
  24. private List<SimpleGrantedAuthority> authorities;
  25. @Override
  26. public Collection<? extends GrantedAuthority> getAuthorities() {
  27. if(authorities!=null){
  28. return authorities;
  29. }
  30. //把permissions中字符串类型的权限信息转换成GrantedAuthority对象存入authorities中
  31. authorities = permissions.stream().map(SimpleGrantedAuthority::new).collect(Collectors.toList());
  32. return authorities;
  33. }
  34. @Override
  35. public boolean isAccountNonExpired() {
  36. return true;
  37. }
  38. @Override
  39. public boolean isAccountNonLocked() {
  40. return true;
  41. }
  42. @Override
  43. public boolean isCredentialsNonExpired() {
  44. return true;
  45. }
  46. @Override
  47. public boolean isEnabled() {
  48. return true;
  49. }
  50. }

封装权限到userDetails对象中 

  1. /**
  2. * @author sl
  3. */
  4. @Service
  5. public class SecurityUserDetailServiceImpl implements UserDetailsService {
  6. @Autowired
  7. private UserMapper userMapper;
  8. @Autowired
  9. private PermMapper permMapper;
  10. @Override
  11. public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
  12. QueryWrapper<User> userQueryWrapper = new QueryWrapper<>();
  13. userQueryWrapper.eq("username",username);
  14. User user = userMapper.selectOne(userQueryWrapper);;
  15. if(Objects.isNull(user)){
  16. throw new RuntimeException("用户名或密码错误");
  17. }
  18. LoginUser loginUser = new LoginUser();
  19. loginUser.setId(user.getId());
  20. loginUser.setUsername(user.getUsername());
  21. loginUser.setPassword(new BCryptPasswordEncoder().encode(user.getPassword()));
  22. //根据用户查询权限信息 添加到LoginUser中
  23. List<Perm> perms= permMapper.findPermByUserId(user.getId());
  24. List<String> permsList = perms.stream().map(s -> s.getPerms()).collect(Collectors.toList());
  25. loginUser.setPermissions(permsList);
  26. return loginUser;
  27. }
  28. }

别忘记在自定义认证器中加入权限进入上下文中

  1. UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(loginUser,null,loginUser.getAuthorities());
  2. SecurityContextHolder.getContext().setAuthentication(authenticationToken);

编写controller加权限注解测试

hasAuthority代表拥有该权限可以访问,还有hasRole等,默认会拼接上ROLE_,在这里不做过多介绍,@PreAuthorize("@myAccess.hasAuthority('audit')"),myAccess为自定义权限校验

  1. /**
  2. * @author sl
  3. */
  4. @RestController
  5. public class TestSecurityAccessController {
  6. /**
  7. * 测试数据访问接口
  8. * @return
  9. */
  10. @GetMapping("/access")
  11. @PreAuthorize("hasAuthority('access')")
  12. public String access(){
  13. return "access success!!";
  14. }
  15. /**
  16. * @PreAuthorize("@myAccess.hasAuthority('audit')")
  17. * 使用自定义权限校验
  18. * @return
  19. */
  20. @GetMapping("/audit")
  21. @PreAuthorize("@myAccess.hasAuthority('audit')")
  22. public String audit(){
  23. return "audit access!!";
  24. }
  25. /**
  26. * 使用spring security权限校验
  27. * @return
  28. */
  29. @GetMapping("/delete")
  30. @PreAuthorize("hasAuthority('delete')")
  31. public String delete(){
  32. return "delete access!!";
  33. }
  34. }

基于配置的权限配置

  1. httpSecurity.authorizeRequests()
  2. .antMatchers("/user/login").anonymous()
  3. // 基于配置的权限处理
  4. .antMatchers("/audit").hasAuthority("audit")
  5. .anyRequest().authenticated()
  6. .and()
  7. .formLogin();

自定义权限校验

在controller中@PreAuthorize("@myAccess.hasAuthority('audit')") 就使用了自定义的权限校验

  1. /**
  2. * @author sl
  3. * 自定义权限校验
  4. */
  5. @Component("myAccess")
  6. public class MyAccessHandler {
  7. public boolean hasAuthority(String authority){
  8. //获取当前用户的权限
  9. Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
  10. LoginUser loginUser = (LoginUser) authentication.getPrincipal();
  11. List<String> permissions = loginUser.getPermissions();
  12. //判断用户权限集合中是否存在authority
  13. return permissions.contains(authority);
  14. }
  15. }

启动项目开始权限测试 

登录测试账户

当前登录的账户ceshi登录成功,当前测试账户具有删除权限

访问无权限的审计功能

当前访问为403,无授权的http状态,无法访问

访问删除功能 

访问成功,代表用户具有的删除权限可以访问,授权成功

认证授权优化问题 

统一返回结果,自定义异常处理器

当前的认证授权,如果失败了返回的结果不是很友好,我们希望在认证失败或者是授权失败的情况下也能和我们的接口一样返回相同结构的json,方便统一结构

spring security的异常处理

  • 如果是认证过程中出现的异常会被封装成AuthenticationException然后调用AuthenticationEntryPoint对象的方法去进行异常处理。
  • ​ 如果是授权过程中出现的异常会被封装成AccessDeniedException然后调用AccessDeniedHandler对象的方法去进行异常处理。
  • ​所以如果我们需要自定义异常处理,我们只需要自定义AuthenticationEntryPoint和AccessDeniedHandler然后配置给SpringSecurity即可。

工具类WebUtils

  1. public class WebUtils {
  2. /**
  3. * 将字符串渲染到客户端
  4. *
  5. * @param response 渲染对象
  6. * @param string 待渲染的字符串
  7. */
  8. public static void renderString(HttpServletResponse response, String string) {
  9. try {
  10. response.setStatus(200);
  11. response.setContentType("application/json");
  12. response.setCharacterEncoding("utf-8");
  13. response.getWriter().print(string);
  14. } catch (IOException e) {
  15. e.printStackTrace();
  16. }
  17. }
  18. }

认证失败处理器

  1. /**
  2. * @author sl
  3. * 认证失败返回处理
  4. */
  5. @Component
  6. public class AuthenticationEntryPointImpl implements AuthenticationEntryPoint {
  7. @Override
  8. public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException authException) throws IOException, ServletException {
  9. Result result = new Result(HttpStatus.UNAUTHORIZED.value(), "用户认证失败,请重新登录");
  10. String json = JSON.toJSONString(result);
  11. // 处理异常,调用工具类
  12. WebUtils.renderString(response, json);
  13. }
  14. }

授权失败处理器

  1. /**
  2. * @author sl
  3. * 权限校验失败处理
  4. */
  5. @Component
  6. public class AccessDeniedHandlerImpl implements AccessDeniedHandler {
  7. @Override
  8. public void handle(HttpServletRequest request, HttpServletResponse response, AccessDeniedException accessDeniedException) throws IOException, ServletException {
  9. Result result = new Result(HttpStatus.FORBIDDEN.value(), "权限不足");
  10. String json = JSON.toJSONString(result);
  11. WebUtils.renderString(response,json);
  12. }
  13. }

将授权以及认证处理器配置给SpringSecurity

  1. /**
  2. * @author sl
  3. */
  4. @EnableWebSecurity
  5. @EnableGlobalMethodSecurity(prePostEnabled = true)
  6. @Configuration
  7. public class SecurityConfig {
  8. @Autowired
  9. private JwtAuthenticationTokenFilter jwtAuthenticationTokenFilter;
  10. @Autowired
  11. private AuthenticationEntryPoint authenticationEntryPoint;
  12. @Autowired
  13. private AccessDeniedHandler accessDeniedHandler;
  14. @Bean
  15. public PasswordEncoder passwordEncoder(){
  16. return new BCryptPasswordEncoder();
  17. }
  18. @Bean
  19. public AuthenticationManager authenticationManager(AuthenticationConfiguration authenticationConfiguration) throws Exception {
  20. return authenticationConfiguration.getAuthenticationManager();
  21. }
  22. @Bean
  23. public SecurityFilterChain securityFilterChain(HttpSecurity httpSecurity) throws Exception {
  24. httpSecurity.csrf().disable();
  25. httpSecurity.authorizeRequests()
  26. .antMatchers("/user/login").anonymous()
  27. // 基于配置的权限处理
  28. // .antMatchers("/audit").hasAuthority("audit")
  29. .anyRequest().authenticated()
  30. .and()
  31. .formLogin();
  32. // 在UsernamePasswordAuthenticationFilter之前添加自定义token前置过滤器
  33. httpSecurity.addFilterBefore(jwtAuthenticationTokenFilter, UsernamePasswordAuthenticationFilter.class);
  34. // 自定义认证失败和权限处理失败处理器
  35. httpSecurity.exceptionHandling().authenticationEntryPoint(authenticationEntryPoint).accessDeniedHandler(accessDeniedHandler);
  36. // 允许跨越
  37. httpSecurity.cors();
  38. return httpSecurity.build();
  39. }
  40. }

测试认证失败返回和授权失败返回 

未登录显示认证失败

登录之后返回权限不足 

项目gitee地址 

https://gitee.com/watcherman/security-service.git

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/Li_阴宅/article/detail/741897
推荐阅读
相关标签
  

闽ICP备14008679号