定制设计Gateway 整合 Spring Security鉴权

目录


Spring Cloud Gateway是基于,和。结果,当您使用Spring Cloud Gateway时,定制设计许多您熟悉的同步库(例如,Spring Data和Spring Security)定制设计和模式可能不适用。定制设计如果您不熟悉这些项目,定制设计建议您在使用Spring Cloud Gateway定制设计之前先阅读它们的文档定制设计以熟悉一些新概念。

Spring-Security

Spring Security定制设计是一个提供身份验证,定制设计授权和保护以防止常见定制设计攻击的框架。定制设计凭借对命令式和响应式定制设计应用程序的一流支持,定制设计它是用于保护基于Spring定制设计的应用程序的事实上的标准。

Spring-Webflux

Spring定制设计框架中包含的原始Web框架Spring Web MVC是专门为Servlet API和Servlet定制设计容器而构建的。定制设计响应式堆栈Web框架Spring WebFlux在稍后的5.0版中添加。定制设计它是完全无阻塞的,支持 背压,并在Netty,Undertow和Servlet 3.1+容器等服务器上运行。

这两个Web框架都反映了其源模块的名称(和 ),并在Spring Framework中并存。每个模块都是可选的。应用程序可以使用一个模块,也可以使用两个模块,在某些情况下,也可以使用两个模块,例如,带有的Spring MVC控制器WebClient

注意

由于Web容器不同,在Gateway项目中使用的WebFlux,是不能和Spring-Web混合使用的。 Spring MVC和 WebFlux 的区别:


编码

项目环境版本

  1. Spring-Cloud:2020.0.1
  2. Spring-Boot: 2.4.3

gradle 依赖

  1. dependencies {
  2. implementation(
  3. 'org.springframework.cloud:spring-cloud-starter-gateway',
  4. 'org.springframework.boot:spring-boot-starter-security'
  5. )
  6. }
  7. 复制代码

Spring-Security配置

spring security设置要采用响应式配置,基于WebFlux中WebFilter实现,与Spring MVC的Security是通过Servlet的Filter实现类似,也是一系列filter组成的过滤链。

Reactor与传统MVC配置对应:

webfluxmvc作用
@EnableWebFluxSecurity@EnableWebSecurity开启security配置
ServerAuthenticationSuccessHandlerAuthenticationSuccessHandler登录成功Handler
ServerAuthenticationFailureHandlerAuthenticationFailureHandler登陆失败Handler
ReactiveAuthorizationManagerAuthorizationManager认证管理
ServerSecurityContextRepositorySecurityContextHolder认证信息存储管理
ReactiveUserDetailsServiceUserDetailsService用户登录
ReactiveAuthorizationManagerAccessDecisionManager鉴权管理
ServerAuthenticationEntryPointAuthenticationEntryPoint未认证Handler
ServerAccessDeniedHandlerAccessDeniedHandler鉴权失败Handler

1. Security核心配置

  1. package com.pluto.gateway.security;
  2. import org.springframework.beans.factory.annotation.Value;
  3. import org.springframework.context.annotation.Bean;
  4. import org.springframework.http.HttpMethod;
  5. import org.springframework.security.authentication.DelegatingReactiveAuthenticationManager;
  6. import org.springframework.security.authentication.ReactiveAuthenticationManager;
  7. import org.springframework.security.authentication.UserDetailsRepositoryReactiveAuthenticationManager;
  8. import org.springframework.security.config.annotation.web.reactive.EnableWebFluxSecurity;
  9. import org.springframework.security.config.web.server.ServerHttpSecurity;
  10. import org.springframework.security.crypto.factory.PasswordEncoderFactories;
  11. import org.springframework.security.crypto.password.PasswordEncoder;
  12. import org.springframework.security.web.server.SecurityWebFilterChain;
  13. import reactor.core.publisher.Mono;
  14. import javax.annotation.Resource;
  15. import java.util.LinkedList;
  16. /**
  17. * @author ShiLei
  18. * @version 1.0.0
  19. * @date 2021/3/11 10:56
  20. * @description webflux security核心配置类
  21. */
  22. @EnableWebFluxSecurity
  23. public class WebfluxSecurityConfig {
  24. @Resource
  25. private DefaultAuthorizationManager defaultAuthorizationManager;
  26. @Resource
  27. private UserDetailsServiceImpl userDetailsServiceImpl;
  28. @Resource
  29. private DefaultAuthenticationSuccessHandler defaultAuthenticationSuccessHandler;
  30. @Resource
  31. private DefaultAuthenticationFailureHandler defaultAuthenticationFailureHandler;
  32. @Resource
  33. private TokenAuthenticationManager tokenAuthenticationManager;
  34. @Resource
  35. private DefaultSecurityContextRepository defaultSecurityContextRepository;
  36. @Resource
  37. private DefaultAuthenticationEntryPoint defaultAuthenticationEntryPoint;
  38. @Resource
  39. private DefaultAccessDeniedHandler defaultAccessDeniedHandler;
  40. /**
  41. * 自定义过滤权限
  42. */
  43. @Value("${security.noFilter}")
  44. private String noFilter;
  45. @Bean
  46. public SecurityWebFilterChain securityWebFilterChain(ServerHttpSecurity httpSecurity) {
  47. httpSecurity
  48. // 登录认证处理
  49. .authenticationManager(reactiveAuthenticationManager())
  50. .securityContextRepository(defaultSecurityContextRepository)
  51. // 请求拦截处理
  52. .authorizeExchange(exchange -> exchange
  53. .pathMatchers(noFilter).permitAll()
  54. .pathMatchers(HttpMethod.OPTIONS).permitAll()
  55. .anyExchange().access(defaultAuthorizationManager)
  56. )
  57. .formLogin()
  58. // 自定义处理
  59. .authenticationSuccessHandler(defaultAuthenticationSuccessHandler)
  60. .authenticationFailureHandler(defaultAuthenticationFailureHandler)
  61. .and()
  62. .exceptionHandling()
  63. .authenticationEntryPoint(defaultAuthenticationEntryPoint)
  64. .and()
  65. .exceptionHandling()
  66. .accessDeniedHandler(defaultAccessDeniedHandler)
  67. .and()
  68. .csrf().disable()
  69. ;
  70. return httpSecurity.build();
  71. }
  72. /**
  73. * BCrypt密码编码
  74. */
  75. @Bean("passwordEncoder")
  76. public PasswordEncoder passwordEncoder() {
  77. return PasswordEncoderFactories.createDelegatingPasswordEncoder();
  78. }
  79. /**
  80. * 注册用户信息验证管理器,可按需求添加多个按顺序执行
  81. */
  82. @Bean
  83. ReactiveAuthenticationManager reactiveAuthenticationManager() {
  84. LinkedList<ReactiveAuthenticationManager> managers = new LinkedList<>();
  85. managers.add(authentication -> {
  86. // 其他登陆方式 (比如手机号验证码登陆) 可在此设置不得抛出异常或者 Mono.error
  87. return Mono.empty();
  88. });
  89. // 必须放最后不然会优先使用用户名密码校验但是用户名密码不对时此 AuthenticationManager 会调用 Mono.error 造成后面的 AuthenticationManager 不生效
  90. managers.add(new UserDetailsRepositoryReactiveAuthenticationManager(userDetailsServiceImpl));
  91. managers.add(tokenAuthenticationManager);
  92. return new DelegatingReactiveAuthenticationManager(managers);
  93. }
  94. }
  95. 复制代码

2.用户认证

  1. package com.pluto.gateway.security;
  2. import org.springframework.security.core.GrantedAuthority;
  3. import org.springframework.security.core.userdetails.User;
  4. import java.io.Serializable;
  5. import java.util.Collection;
  6. /**
  7. * @author ShiLei
  8. * @version 1.0.0
  9. * @date 2021/3/10 13:15
  10. * @description 自定义用户信息
  11. */
  12. public class SecurityUserDetails extends User implements Serializable {
  13. private Long userId;
  14. public SecurityUserDetails(String username, String password, Collection<? extends GrantedAuthority> authorities, Long userId) {
  15. super(username, password, authorities);
  16. this.userId = userId;
  17. }
  18. public SecurityUserDetails(String username, String password, boolean enabled, boolean accountNonExpired, boolean credentialsNonExpired, boolean accountNonLocked, Collection<? extends GrantedAuthority> authorities, Long userId) {
  19. super(username, password, enabled, accountNonExpired, credentialsNonExpired, accountNonLocked, authorities);
  20. this.userId = userId;
  21. }
  22. public Long getUserId() {
  23. return userId;
  24. }
  25. public void setUserId(Long userId) {
  26. this.userId = userId;
  27. }
  28. }
  29. 复制代码
  1. package com.pluto.gateway.security;
  2. import org.springframework.security.core.userdetails.ReactiveUserDetailsPasswordService;
  3. import org.springframework.security.core.userdetails.ReactiveUserDetailsService;
  4. import org.springframework.security.core.userdetails.UserDetails;
  5. import org.springframework.security.crypto.password.PasswordEncoder;
  6. import org.springframework.stereotype.Service;
  7. import reactor.core.publisher.Mono;
  8. import javax.annotation.Resource;
  9. import java.util.ArrayList;
  10. /**
  11. * @author ceshi
  12. * @date 2021/3/9 14:03
  13. * @description 用户登录处理
  14. * @version 1.0.0
  15. */@Service
  16. public class UserDetailsServiceImpl implements ReactiveUserDetailsService {
  17. @Resource
  18. private PasswordEncoder passwordEncoder;
  19. @Override
  20. public Mono<UserDetails> findByUsername(String username) {
  21. SecurityUserDetails securityUserDetails = new SecurityUserDetails(
  22. "user",
  23. passwordEncoder.encode("user"),
  24. true, true, true, true, new ArrayList<>(),
  25. 1L
  26. );
  27. return Mono.just(securityUserDetails);
  28. }
  29. }
  30. 复制代码

3.1 自定义登录成功

  1. package com.pluto.gateway.security;
  2. import com.alibaba.fastjson.JSONObject;
  3. import com.pluto.common.basic.utils.JwtTokenUtil;
  4. import com.pluto.common.basic.utils.ResultVoUtil;
  5. import org.springframework.beans.factory.annotation.Value;
  6. import org.springframework.core.io.buffer.DataBuffer;
  7. import org.springframework.core.io.buffer.DataBufferFactory;
  8. import org.springframework.security.core.Authentication;
  9. import org.springframework.security.web.server.WebFilterExchange;
  10. import org.springframework.security.web.server.authentication.ServerAuthenticationSuccessHandler;
  11. import org.springframework.stereotype.Component;
  12. import reactor.core.publisher.Mono;
  13. import java.util.HashMap;
  14. import java.util.Map;
  15. /**
  16. * @author ShiLei
  17. * @version 1.0.0
  18. * @date 2021/3/11 15:00
  19. * @description 登录成功处理
  20. */
  21. @Component
  22. public class DefaultAuthenticationSuccessHandler implements ServerAuthenticationSuccessHandler {
  23. /**
  24. * token 过期时间
  25. */
  26. @Value("${jwt.token.expired}")
  27. private int jwtTokenExpired;
  28. /**
  29. * 刷新token 时间
  30. */
  31. @Value("${jwt.token.refresh.expired}")
  32. private int jwtTokenRefreshExpired;
  33. @Override
  34. public Mono<Void> onAuthenticationSuccess(WebFilterExchange webFilterExchange, Authentication authentication) {
  35. return Mono.defer(() -> Mono.just(webFilterExchange.getExchange().getResponse()).flatMap(response -> {
  36. DataBufferFactory dataBufferFactory = response.bufferFactory();
  37. // 生成JWT token
  38. Map<String, Object> map = new HashMap<>(2);
  39. SecurityUserDetails userDetails = (SecurityUserDetails) authentication.getPrincipal();
  40. map.put("userId", userDetails.getUserId());
  41. map.put("username", userDetails.getUsername());
  42. map.put("roles",userDetails.getAuthorities());
  43. String token = JwtTokenUtil.generateToken(map, userDetails.getUsername(), jwtTokenExpired);
  44. String refreshToken = JwtTokenUtil.generateToken(map, userDetails.getUsername(), jwtTokenRefreshExpired);
  45. Map<String, Object> tokenMap = new HashMap<>(2);
  46. tokenMap.put("token", token);
  47. tokenMap.put("refreshToken", refreshToken);
  48. DataBuffer dataBuffer = dataBufferFactory.wrap(JSONObject.toJSONString(ResultVoUtil.success(tokenMap)).getBytes());
  49. return response.writeWith(Mono.just(dataBuffer));
  50. }));
  51. }
  52. }
  53. 复制代码

3.2 自定义登录失败Handler

  1. package com.pluto.gateway.security;
  2. import com.alibaba.fastjson.JSONObject;
  3. import com.pluto.common.basic.enums.UserStatusCodeEnum;
  4. import com.pluto.common.basic.utils.ResultVoUtil;
  5. import com.pluto.common.basic.vo.ResultVO;
  6. import org.springframework.core.io.buffer.DataBuffer;
  7. import org.springframework.core.io.buffer.DataBufferFactory;
  8. import org.springframework.security.authentication.*;
  9. import org.springframework.security.core.AuthenticationException;
  10. import org.springframework.security.core.userdetails.UsernameNotFoundException;
  11. import org.springframework.security.web.server.WebFilterExchange;
  12. import org.springframework.security.web.server.authentication.ServerAuthenticationFailureHandler;
  13. import org.springframework.stereotype.Component;
  14. import reactor.core.publisher.Mono;
  15. import java.util.Map;
  16. /**
  17. * @author ShiLei
  18. * @version 1.0.0
  19. * @date 2021/3/11 15:14
  20. * @description 登录失败处理
  21. */
  22. @Component
  23. public class DefaultAuthenticationFailureHandler implements ServerAuthenticationFailureHandler {
  24. @Override
  25. public Mono<Void> onAuthenticationFailure(WebFilterExchange webFilterExchange, AuthenticationException exception) {
  26. return Mono.defer(() -> Mono.just(webFilterExchange.getExchange()
  27. .getResponse()).flatMap(response -> {
  28. DataBufferFactory dataBufferFactory = response.bufferFactory();
  29. ResultVO<Map<String, Object>> resultVO = ResultVoUtil.error();
  30. // 账号不存在
  31. if (exception instanceof UsernameNotFoundException) {
  32. resultVO = ResultVoUtil.failed(UserStatusCodeEnum.ACCOUNT_NOT_EXIST);
  33. // 用户名或密码错误
  34. } else if (exception instanceof BadCredentialsException) {
  35. resultVO = ResultVoUtil.failed(UserStatusCodeEnum.LOGIN_PASSWORD_ERROR);
  36. // 账号已过期
  37. } else if (exception instanceof AccountExpiredException) {
  38. resultVO = ResultVoUtil.failed(UserStatusCodeEnum.ACCOUNT_EXPIRED);
  39. // 账号已被锁定
  40. } else if (exception instanceof LockedException) {
  41. resultVO = ResultVoUtil.failed(UserStatusCodeEnum.ACCOUNT_LOCKED);
  42. // 用户凭证已失效
  43. } else if (exception instanceof CredentialsExpiredException) {
  44. resultVO = ResultVoUtil.failed(UserStatusCodeEnum.ACCOUNT_CREDENTIAL_EXPIRED);
  45. // 账号已被禁用
  46. } else if (exception instanceof DisabledException) {
  47. resultVO = ResultVoUtil.failed(UserStatusCodeEnum.ACCOUNT_DISABLE);
  48. }
  49. DataBuffer dataBuffer = dataBufferFactory.wrap(JSONObject.toJSONString(resultVO).getBytes());
  50. return response.writeWith(Mono.just(dataBuffer));
  51. }));
  52. }
  53. }
  54. 复制代码

3.3 自定义未认证Handler

  1. package com.pluto.gateway.security;
  2. import com.alibaba.fastjson.JSONObject;
  3. import com.pluto.common.basic.enums.UserStatusCodeEnum;
  4. import com.pluto.common.basic.utils.ResultVoUtil;
  5. import org.springframework.core.io.buffer.DataBuffer;
  6. import org.springframework.core.io.buffer.DataBufferFactory;
  7. import org.springframework.http.HttpStatus;
  8. import org.springframework.http.MediaType;
  9. import org.springframework.security.core.AuthenticationException;
  10. import org.springframework.security.web.server.ServerAuthenticationEntryPoint;
  11. import org.springframework.stereotype.Component;
  12. import org.springframework.web.server.ServerWebExchange;
  13. import reactor.core.publisher.Mono;
  14. import java.nio.charset.Charset;
  15. /**
  16. * @author ShiLei
  17. * @version 1.0.0
  18. * @date 2021/3/11 15:17
  19. * @description 未认证处理
  20. */
  21. @Component
  22. public class DefaultAuthenticationEntryPoint implements ServerAuthenticationEntryPoint {
  23. @Override
  24. public Mono<Void> commence(ServerWebExchange exchange, AuthenticationException ex) {
  25. return Mono.defer(() -> Mono.just(exchange.getResponse())).flatMap(response -> {
  26. response.setStatusCode(HttpStatus.UNAUTHORIZED);
  27. response.getHeaders().setContentType(MediaType.APPLICATION_JSON);
  28. DataBufferFactory dataBufferFactory = response.bufferFactory();
  29. String result = JSONObject.toJSONString(ResultVoUtil.failed(UserStatusCodeEnum.USER_UNAUTHORIZED));
  30. DataBuffer buffer = dataBufferFactory.wrap(result.getBytes(
  31. Charset.defaultCharset()));
  32. return response.writeWith(Mono.just(buffer));
  33. });
  34. }
  35. }
  36. 复制代码

3.4 自定义鉴权失败Handler

  1. package com.pluto.gateway.security;
  2. import com.alibaba.fastjson.JSONObject;
  3. import com.pluto.common.basic.enums.UserStatusCodeEnum;
  4. import com.pluto.common.basic.utils.ResultVoUtil;
  5. import org.springframework.core.io.buffer.DataBuffer;
  6. import org.springframework.core.io.buffer.DataBufferFactory;
  7. import org.springframework.http.HttpStatus;
  8. import org.springframework.http.MediaType;
  9. import org.springframework.security.access.AccessDeniedException;
  10. import org.springframework.security.web.server.authorization.ServerAccessDeniedHandler;
  11. import org.springframework.stereotype.Component;
  12. import org.springframework.web.server.ServerWebExchange;
  13. import reactor.core.publisher.Mono;
  14. import java.nio.charset.Charset;
  15. /**
  16. * @author ShiLei
  17. * @version 1.0.0
  18. * @date 2021/3/11 11:12
  19. * @description 鉴权管理
  20. */
  21. @Component
  22. public class DefaultAccessDeniedHandler implements ServerAccessDeniedHandler {
  23. @Override
  24. public Mono<Void> handle(ServerWebExchange exchange, AccessDeniedException denied) {
  25. return Mono.defer(() -> Mono.just(exchange.getResponse()))
  26. .flatMap(response -> {
  27. response.setStatusCode(HttpStatus.OK);
  28. response.getHeaders().setContentType(MediaType.APPLICATION_JSON);
  29. DataBufferFactory dataBufferFactory = response.bufferFactory();
  30. String result = JSONObject.toJSONString(ResultVoUtil.failed(UserStatusCodeEnum.PERMISSION_DENIED));
  31. DataBuffer buffer = dataBufferFactory.wrap(result.getBytes(
  32. Charset.defaultCharset()));
  33. return response.writeWith(Mono.just(buffer));
  34. });
  35. }
  36. }
  37. 复制代码

4.自定义JWT Token认证管理

  1. package com.pluto.gateway.security;
  2. import org.apache.commons.lang3.StringUtils;
  3. import org.springframework.http.server.reactive.ServerHttpRequest;
  4. import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
  5. import org.springframework.security.core.context.SecurityContext;
  6. import org.springframework.security.core.context.SecurityContextImpl;
  7. import org.springframework.security.web.server.context.ServerSecurityContextRepository;
  8. import org.springframework.stereotype.Component;
  9. import org.springframework.util.CollectionUtils;
  10. import org.springframework.web.server.ServerWebExchange;
  11. import reactor.core.publisher.Mono;
  12. import javax.annotation.Resource;
  13. import java.util.List;
  14. /**
  15. * @author ShiLei
  16. * @version 1.0.0
  17. * @date 2021/3/11 16:27
  18. * @description 存储认证授权的相关信息
  19. */
  20. @Component
  21. public class DefaultSecurityContextRepository implements ServerSecurityContextRepository {
  22. public final static String TOKEN_HEADER = "Authorization";
  23. public final static String BEARER = "Bearer ";
  24. @Resource
  25. private TokenAuthenticationManager tokenAuthenticationManager;
  26. @Override
  27. public Mono<Void> save(ServerWebExchange exchange, SecurityContext context) {
  28. return Mono.empty();
  29. }
  30. @Override
  31. public Mono<SecurityContext> load(ServerWebExchange exchange) {
  32. ServerHttpRequest request = exchange.getRequest();
  33. List<String> headers = request.getHeaders().get(TOKEN_HEADER);
  34. if (!CollectionUtils.isEmpty(headers)) {
  35. String authorization = headers.get(0);
  36. if (StringUtils.isNotEmpty(authorization)) {
  37. String token = authorization.substring(BEARER.length());
  38. if (StringUtils.isNotEmpty(token)) {
  39. return tokenAuthenticationManager.authenticate(
  40. new UsernamePasswordAuthenticationToken(token, null)
  41. ).map(SecurityContextImpl::new);
  42. }
  43. }
  44. }
  45. return Mono.empty();
  46. }
  47. }
  48. 复制代码
  1. package com.pluto.gateway.security;
  2. import com.pluto.common.basic.utils.JwtTokenUtil;
  3. import org.springframework.context.annotation.Primary;
  4. import org.springframework.security.authentication.ReactiveAuthenticationManager;
  5. import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
  6. import org.springframework.security.core.Authentication;
  7. import org.springframework.security.core.GrantedAuthority;
  8. import org.springframework.stereotype.Component;
  9. import reactor.core.publisher.Mono;
  10. import java.util.Collection;
  11. /**
  12. * @author ShiLei
  13. * @version 1.0.0
  14. * @date 2021/3/11 13:23
  15. * @description token 认证处理
  16. */
  17. @Component
  18. @Primary
  19. public class TokenAuthenticationManager implements ReactiveAuthenticationManager {
  20. @Override
  21. @SuppressWarnings("unchecked")
  22. public Mono<Authentication> authenticate(Authentication authentication) {
  23. return Mono.just(authentication)
  24. .map(auth -> JwtTokenUtil.parseJwtRsa256(auth.getPrincipal().toString()))
  25. .map(claims -> {
  26. Collection<? extends GrantedAuthority> roles = (Collection<? extends GrantedAuthority>) claims.get("roles");
  27. return new UsernamePasswordAuthenticationToken(
  28. claims.getSubject(),
  29. null,
  30. roles
  31. );
  32. });
  33. }
  34. }
  35. 复制代码

5.自定义鉴权管理

  1. package com.pluto.gateway.security;
  2. import com.alibaba.fastjson.JSONObject;
  3. import com.pluto.common.basic.enums.UserStatusCodeEnum;
  4. import com.pluto.common.basic.utils.ResultVoUtil;
  5. import lombok.extern.slf4j.Slf4j;
  6. import org.springframework.http.server.reactive.ServerHttpRequest;
  7. import org.springframework.security.access.AccessDeniedException;
  8. import org.springframework.security.authorization.AuthorizationDecision;
  9. import org.springframework.security.authorization.ReactiveAuthorizationManager;
  10. import org.springframework.security.core.Authentication;
  11. import org.springframework.security.core.GrantedAuthority;
  12. import org.springframework.security.web.server.authorization.AuthorizationContext;
  13. import org.springframework.stereotype.Component;
  14. import org.springframework.util.AntPathMatcher;
  15. import org.springframework.web.server.ServerWebExchange;
  16. import reactor.core.publisher.Mono;
  17. import java.util.Collection;
  18. /**
  19. * @author ShiLei
  20. * @version 1.0.0
  21. * @date 2021/3/11 13:10
  22. * @description 用户权限鉴权处理
  23. */
  24. @Component
  25. @Slf4j
  26. public class DefaultAuthorizationManager implements ReactiveAuthorizationManager<AuthorizationContext> {
  27. private final AntPathMatcher antPathMatcher = new AntPathMatcher();
  28. @Override
  29. public Mono<AuthorizationDecision> check(Mono<Authentication> authentication, AuthorizationContext authorizationContext) {
  30. return authentication.map(auth -> {
  31. ServerWebExchange exchange = authorizationContext.getExchange();
  32. ServerHttpRequest request = exchange.getRequest();
  33. Collection<? extends GrantedAuthority> authorities = auth.getAuthorities();
  34. for (GrantedAuthority authority : authorities) {
  35. String authorityAuthority = authority.getAuthority();
  36. String path = request.getURI().getPath();
  37. // TODO
  38. // 查询用户访问所需角色进行对比
  39. if (antPathMatcher.match(authorityAuthority, path)) {
  40. log.info(String.format("用户请求API校验通过,GrantedAuthority:{%s} Path:{%s} ", authorityAuthority, path));
  41. return new AuthorizationDecision(true);
  42. }
  43. }
  44. return new AuthorizationDecision(false);
  45. }).defaultIfEmpty(new AuthorizationDecision(false));
  46. }
  47. @Override
  48. public Mono<Void> verify(Mono<Authentication> authentication, AuthorizationContext object) {
  49. return check(authentication, object)
  50. .filter(AuthorizationDecision::isGranted)
  51. .switchIfEmpty(Mono.defer(() -> {
  52. String body = JSONObject.toJSONString(ResultVoUtil.failed(UserStatusCodeEnum.PERMISSION_DENIED));
  53. return Mono.error(new AccessDeniedException(body));
  54. })).flatMap(d -> Mono.empty());
  55. }
  56. }
  57. 复制代码

2.springsecruity密码判断

下面看看是哪里进行的密码比较

1 /spring-security-core-5.1.4.RELEASE-sources.jar!/org/springframework/security/authentication/dao/AbstractUserDetailsAuthenticationProvider.java

  1. public Authentication authenticate(Authentication authentication)  
  2.       throws AuthenticationException {
  3.  
  4.    ......
  5.    try {
  6.       preAuthenticationChecks.check(user);
  7.       // 重点看 additionalAuthenticationChecks 密码判断
  8.       additionalAuthenticationChecks(user,(UsernamePasswordAuthenticationToken) authentication);         
  9.    }
  10.    catch (AuthenticationException exception) {
  11.       if (cacheWasUsed) {
  12.          // There was a problem, so try again after checking
  13.          // we're using latest data (i.e. not from the cache)
  14.          cacheWasUsed = false;
  15.          user = retrieveUser(username,
  16.                (UsernamePasswordAuthenticationToken) authentication);
  17.          preAuthenticationChecks.check(user);
  18.          additionalAuthenticationChecks(user,
  19.                (UsernamePasswordAuthenticationToken) authentication);
  20.       }
  21.       else {
  22.          throw exception;
  23.       }
  24.    }
  25.  
  26.  
  27.    postAuthenticationChecks.check(user);
  28.  
  29.  
  30.   ......
  31.  
  32.    return createSuccessAuthentication(principalToReturn, authentication, user);
  33. }


 

  1. 2 /spring-security-core-5.1.4.RELEASE-sources.jar!/org/springframework/security/authentication/dao/DaoAuthenticationProvider.java
  2. protected void additionalAuthenticationChecks(UserDetails userDetails,
  3.       UsernamePasswordAuthenticationToken authentication)
  4.       throws AuthenticationException {
  5.    if (authentication.getCredentials() == null) {
  6.       logger.debug("Authentication failed: no credentials provided");
  7.  
  8.  
  9.       throw new BadCredentialsException(messages.getMessage(
  10.             "AbstractUserDetailsAuthenticationProvider.badCredentials",
  11.             "Bad credentials"));
  12.    }
  13.  
  14.  
  15.    String presentedPassword = authentication.getCredentials().toString();
  16.    // 密码比较就在这个地方,前面这个是用户输入的密码,后面这个是数据库存的密码,一致则通过
  17.    if (!passwordEncoder.matches(presentedPassword, userDetails.getPassword())) {
  18.       logger.debug("Authentication failed: password does not match stored value");
  19.  
  20.  
  21.       throw new BadCredentialsException(messages.getMessage(
  22.             "AbstractUserDetailsAuthenticationProvider.badCredentials",
  23.             "Bad credentials"));
  24.    }
  25. }

3.流程

 

 

 

用户信息 还可以存放权限信息

 

3.尚硅谷springsecurity

 

 

 

3.3两个重要接口 

3.3.1认证

 

 

 3.3.2自定义登入

3.3.3

 

 

 403设计

3.5注解访问

 

 3.5用户注销

3.6免登陆

 

 

密码

4过滤器方式

4.1maven---直接引用--配置

  1. package com.atguigu.serurity.config;
  2. import com.atguigu.serurity.filter.TokenAuthenticationFilter;
  3. import com.atguigu.serurity.filter.TokenLoginFilter;
  4. import com.atguigu.serurity.security.DefaultPasswordEncoder;
  5. import com.atguigu.serurity.security.TokenLogoutHandler;
  6. import com.atguigu.serurity.security.TokenManager;
  7. import com.atguigu.serurity.security.UnauthorizedEntryPoint;
  8. import org.springframework.beans.factory.annotation.Autowired;
  9. import org.springframework.context.annotation.Configuration;
  10. import org.springframework.data.redis.core.RedisTemplate;
  11. import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
  12. import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
  13. import org.springframework.security.config.annotation.web.builders.HttpSecurity;
  14. import org.springframework.security.config.annotation.web.builders.WebSecurity;
  15. import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
  16. import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
  17. import org.springframework.security.core.userdetails.UserDetailsService;
  18. /**
  19. * <p>
  20. * Security配置类
  21. * </p>
  22. *
  23. * @author qy
  24. * @since 2019-11-18
  25. */
  26. @Configuration
  27. @EnableWebSecurity
  28. @EnableGlobalMethodSecurity(prePostEnabled = true)
  29. public class TokenWebSecurityConfig extends WebSecurityConfigurerAdapter {
  30. private UserDetailsService userDetailsService;//用户详情服务
  31. private TokenManager tokenManager;//令牌管理器
  32. private DefaultPasswordEncoder defaultPasswordEncoder;//默认密码编码器
  33. private RedisTemplate redisTemplate;//Redis 模板
  34. //令牌网络安全配置
  35. @Autowired
  36. public TokenWebSecurityConfig(UserDetailsService userDetailsService, DefaultPasswordEncoder defaultPasswordEncoder,
  37. TokenManager tokenManager, RedisTemplate redisTemplate) {
  38. this.userDetailsService = userDetailsService;
  39. this.defaultPasswordEncoder = defaultPasswordEncoder;
  40. this.tokenManager = tokenManager;
  41. this.redisTemplate = redisTemplate;
  42. }
  43. /**
  44. * 配置设置
  45. * @param http
  46. * @throws Exception
  47. */
  48. @Override
  49. protected void configure(HttpSecurity http) throws Exception {
  50. System.out.println("configure(HttpSecurity http)"+http);
  51. http.exceptionHandling()
  52. .authenticationEntryPoint(new UnauthorizedEntryPoint())
  53. .and().csrf().disable()
  54. .authorizeRequests()
  55. .anyRequest().authenticated()
  56. .and().logout().logoutUrl("/admin/acl/index/logout")
  57. .addLogoutHandler(new TokenLogoutHandler(tokenManager,redisTemplate)).and()
  58. .addFilter(new TokenLoginFilter(authenticationManager(), tokenManager, redisTemplate))
  59. .addFilter(new TokenAuthenticationFilter(authenticationManager(), tokenManager, redisTemplate)).httpBasic();
  60. }
  61. /**
  62. * 密码处理
  63. * @param auth
  64. * @throws Exception
  65. * 身份验证管理器生成器
  66. */
  67. @Override
  68. public void configure(AuthenticationManagerBuilder auth) throws Exception {
  69. auth.userDetailsService(userDetailsService).passwordEncoder(defaultPasswordEncoder);
  70. }
  71. /**
  72. * 配置哪些请求不拦截
  73. * @param web
  74. * @throws Exception
  75. */
  76. @Override
  77. public void configure(WebSecurity web) throws Exception {
  78. web.ignoring().antMatchers("/api/**",
  79. "/swagger-resources/**", "/webjars/**", "/v2/**", "/swagger-ui.html/**"
  80. );
  81. }
  82. }

4.2 entity

  1. package com.atguigu.serurity.entity;
  2. import lombok.Data;
  3. import lombok.extern.slf4j.Slf4j;
  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 org.springframework.util.StringUtils;
  8. import java.util.ArrayList;
  9. import java.util.Collection;
  10. import java.util.List;
  11. /**
  12. * <p>
  13. * 安全认证用户详情信息
  14. * </p>
  15. *
  16. * @author qy
  17. * @since 2019-11-08
  18. */
  19. @Data
  20. @Slf4j
  21. public class SecurityUser implements UserDetails {
  22. //当前登录用户
  23. private transient User currentUserInfo;
  24. //当前权限
  25. private List<String> permissionValueList;
  26. public SecurityUser() {
  27. }
  28. public SecurityUser(User user) {
  29. if (user != null) {
  30. this.currentUserInfo = user;
  31. }
  32. }
  33. @Override
  34. public Collection<? extends GrantedAuthority> getAuthorities() {
  35. Collection<GrantedAuthority> authorities = new ArrayList<>();
  36. for(String permissionValue : permissionValueList) {
  37. if(StringUtils.isEmpty(permissionValue)) continue;
  38. SimpleGrantedAuthority authority = new SimpleGrantedAuthority(permissionValue);
  39. authorities.add(authority);
  40. }
  41. return authorities;
  42. }
  43. @Override
  44. public String getPassword() {
  45. return currentUserInfo.getPassword();
  46. }
  47. @Override
  48. public String getUsername() {
  49. return currentUserInfo.getUsername();
  50. }
  51. @Override
  52. public boolean isAccountNonExpired() {
  53. return true;
  54. }
  55. @Override
  56. public boolean isAccountNonLocked() {
  57. return true;
  58. }
  59. @Override
  60. public boolean isCredentialsNonExpired() {
  61. return true;
  62. }
  63. @Override
  64. public boolean isEnabled() {
  65. return true;
  66. }
  67. }

  1. package com.atguigu.serurity.entity;
  2. import io.swagger.annotations.ApiModel;
  3. import io.swagger.annotations.ApiModelProperty;
  4. import lombok.Builder;
  5. import lombok.Data;
  6. import java.io.Serializable;
  7. /**
  8. * <p>
  9. * 用户实体类
  10. * </p>
  11. *
  12. * @author qy
  13. * @since 2019-11-08
  14. */
  15. @Data
  16. @ApiModel(description = "用户实体类")
  17. public class User implements Serializable {
  18. private static final long serialVersionUID = 1L;
  19. @ApiModelProperty(value = "微信openid")
  20. private String username;
  21. @ApiModelProperty(value = "密码")
  22. private String password;
  23. @ApiModelProperty(value = "昵称")
  24. private String nickName;
  25. @ApiModelProperty(value = "用户头像")
  26. private String salt;
  27. @ApiModelProperty(value = "用户签名")
  28. private String token;
  29. }

4.3 filter

   4.3.1 访问过滤器  获取request--token

  1. package com.atguigu.serurity.filter;
  2. import com.atguigu.commonutils.R;
  3. import com.atguigu.commonutils.ResponseUtil;
  4. import com.atguigu.serurity.security.TokenManager;
  5. import org.springframework.data.redis.core.RedisTemplate;
  6. import org.springframework.security.authentication.AuthenticationManager;
  7. import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
  8. import org.springframework.security.core.GrantedAuthority;
  9. import org.springframework.security.core.authority.SimpleGrantedAuthority;
  10. import org.springframework.security.core.context.SecurityContextHolder;
  11. import org.springframework.security.web.authentication.www.BasicAuthenticationFilter;
  12. import org.springframework.util.StringUtils;
  13. import javax.servlet.FilterChain;
  14. import javax.servlet.ServletException;
  15. import javax.servlet.http.HttpServletRequest;
  16. import javax.servlet.http.HttpServletResponse;
  17. import java.io.IOException;
  18. import java.util.ArrayList;
  19. import java.util.Collection;
  20. import java.util.List;
  21. /**
  22. * <p>
  23. * 访问过滤器
  24. * </p>
  25. *
  26. * @author qy
  27. * @since 2019-11-08
  28. */
  29. public class TokenAuthenticationFilter extends BasicAuthenticationFilter {
  30. private TokenManager tokenManager;
  31. private RedisTemplate redisTemplate;
  32. public TokenAuthenticationFilter(AuthenticationManager authManager, TokenManager tokenManager,RedisTemplate redisTemplate) {
  33. super(authManager);
  34. this.tokenManager = tokenManager;
  35. this.redisTemplate = redisTemplate;
  36. }
  37. @Override
  38. protected void doFilterInternal(HttpServletRequest req, HttpServletResponse res, FilterChain chain)
  39. throws IOException, ServletException {
  40. logger.info("=======TokenAuthenticationFilter-doFilterInternal=========="+req.getRequestURI());
  41. System.out.println("req.getRequestURI().indexOf(\"admin\")"+req.getRequestURI().indexOf("admin"));
  42. System.out.println("doFilterInternal-req"+req);
  43. System.out.println("doFilterInternal-req.getRequestURI()"+req.getRequestURI());
  44. // if(req.getRequestURI().indexOf("admin") == 1) {
  45. // chain.doFilter(req, res);
  46. // return;
  47. // }
  48. UsernamePasswordAuthenticationToken authentication = null;
  49. try {
  50. authentication = getAuthentication(req);
  51. System.out.println("doFilterInternal-authentication"+authentication);
  52. } catch (Exception e) {
  53. ResponseUtil.out(res, R.error());
  54. }
  55. if (authentication != null) {
  56. SecurityContextHolder.getContext().setAuthentication(authentication);
  57. } else {
  58. ResponseUtil.out(res, R.error());
  59. }
  60. /*将请求转发给过滤器链上下一个对象。这里的下一个指的是下一个filter,
  61. 如果没有filter那就是你请求的资源。 一般filter都是一个链,web.xml 里面配置了几个就有几个。
  62. 一个一个的连在一起 request -> filter1 -> filter2 ->filter3 -> .... -> request resource.
  63. */
  64. chain.doFilter(req, res);
  65. }
  66. private UsernamePasswordAuthenticationToken getAuthentication(HttpServletRequest request) {
  67. // token置于header里
  68. String token = request.getHeader("token");
  69. if (token != null && !"".equals(token.trim())) {
  70. String userName = tokenManager.getUserFromToken(token);
  71. List<String> permissionValueList = (List<String>) redisTemplate.opsForValue().get(userName);
  72. Collection<GrantedAuthority> authorities = new ArrayList<>();
  73. for(String permissionValue : permissionValueList) {
  74. if(StringUtils.isEmpty(permissionValue)) continue;
  75. SimpleGrantedAuthority authority = new SimpleGrantedAuthority(permissionValue);
  76. authorities.add(authority);
  77. }
  78. if (!StringUtils.isEmpty(userName)) {
  79. return new UsernamePasswordAuthenticationToken(userName, token, authorities);
  80. }
  81. return null;
  82. }
  83. return null;
  84. }
  85. }

 4.3.2 登录过滤器   成功 获取token 保存redis

  1. package com.atguigu.serurity.filter;
  2. import com.atguigu.commonutils.R;
  3. import com.atguigu.commonutils.ResponseUtil;
  4. import com.atguigu.serurity.entity.SecurityUser;
  5. import com.atguigu.serurity.entity.User;
  6. import com.atguigu.serurity.security.TokenManager;
  7. import com.fasterxml.jackson.databind.ObjectMapper;
  8. import org.springframework.data.redis.core.RedisTemplate;
  9. import org.springframework.security.authentication.AuthenticationManager;
  10. import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
  11. import org.springframework.security.core.Authentication;
  12. import org.springframework.security.core.AuthenticationException;
  13. import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
  14. import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
  15. import javax.servlet.FilterChain;
  16. import javax.servlet.ServletException;
  17. import javax.servlet.http.HttpServletRequest;
  18. import javax.servlet.http.HttpServletResponse;
  19. import java.io.IOException;
  20. import java.util.ArrayList;
  21. /**
  22. * <p>
  23. * 登录过滤器,继承UsernamePasswordAuthenticationFilter,对用户名密码进行登录校验
  24. * </p>
  25. *
  26. * @author qy
  27. * @since 2019-11-08
  28. */
  29. public class TokenLoginFilter extends UsernamePasswordAuthenticationFilter {
  30. private AuthenticationManager authenticationManager;
  31. private TokenManager tokenManager;
  32. private RedisTemplate redisTemplate;
  33. public TokenLoginFilter(AuthenticationManager authenticationManager, TokenManager tokenManager, RedisTemplate redisTemplate) {
  34. this.authenticationManager = authenticationManager;
  35. this.tokenManager = tokenManager;
  36. this.redisTemplate = redisTemplate;
  37. this.setPostOnly(false);
  38. this.setRequiresAuthenticationRequestMatcher(new AntPathRequestMatcher("/admin/acl/login","POST"));
  39. }
  40. @Override
  41. public Authentication attemptAuthentication(HttpServletRequest req, HttpServletResponse res)
  42. throws AuthenticationException {
  43. try {
  44. User user = new ObjectMapper().readValue(req.getInputStream(), User.class);
  45. return authenticationManager.authenticate(new UsernamePasswordAuthenticationToken(user.getUsername(), user.getPassword(), new ArrayList<>()));
  46. } catch (IOException e) {
  47. throw new RuntimeException(e);
  48. }
  49. }
  50. /**
  51. * 登录成功
  52. * @param req
  53. * @param res
  54. * @param chain
  55. * @param auth
  56. * @throws IOException
  57. * @throws ServletException
  58. */
  59. @Override
  60. protected void successfulAuthentication(HttpServletRequest req, HttpServletResponse res, FilterChain chain,
  61. Authentication auth) throws IOException, ServletException {
  62. SecurityUser user = (SecurityUser) auth.getPrincipal();
  63. String token = tokenManager.createToken(user.getCurrentUserInfo().getUsername());
  64. redisTemplate.opsForValue().set(user.getCurrentUserInfo().getUsername(), user.getPermissionValueList());
  65. ResponseUtil.out(res, R.ok().data("token", token));
  66. }
  67. /**
  68. * 登录失败
  69. * @param request
  70. * @param response
  71. * @param e
  72. * @throws IOException
  73. * @throws ServletException
  74. */
  75. @Override
  76. protected void unsuccessfulAuthentication(HttpServletRequest request, HttpServletResponse response,
  77. AuthenticationException e) throws IOException, ServletException {
  78. ResponseUtil.out(response, R.error());
  79. }
  80. }

 4.4密码的处理方法类型

  1. package com.atguigu.serurity.security;
  2. import com.atguigu.commonutils.MD5;
  3. import org.springframework.security.crypto.password.PasswordEncoder;
  4. import org.springframework.stereotype.Component;
  5. /**
  6. * <p>
  7. * t密码的处理方法类型
  8. * </p>
  9. *
  10. * @author qy
  11. * @since 2019-11-08
  12. */
  13. @Component
  14. public class DefaultPasswordEncoder implements PasswordEncoder {
  15. public DefaultPasswordEncoder() {
  16. this(-1);
  17. }
  18. /**
  19. * @param strength
  20. * the log rounds to use, between 4 and 31
  21. */
  22. public DefaultPasswordEncoder(int strength) {
  23. }
  24. /*
  25. * 密码加密
  26. * */
  27. public String encode(CharSequence rawPassword) {
  28. return MD5.encrypt(rawPassword.toString());
  29. }
  30. /*
  31. * 密码是否相等
  32. * */
  33. public boolean matches(CharSequence rawPassword, String encodedPassword) {
  34. return encodedPassword.equals(MD5.encrypt(rawPassword.toString()));
  35. }
  36. }

 4.4退出

  1. package com.atguigu.serurity.security;
  2. import com.atguigu.commonutils.R;
  3. import com.atguigu.commonutils.ResponseUtil;
  4. import org.springframework.data.redis.core.RedisTemplate;
  5. import org.springframework.security.core.Authentication;
  6. import org.springframework.security.web.authentication.logout.LogoutHandler;
  7. import javax.servlet.http.HttpServletRequest;
  8. import javax.servlet.http.HttpServletResponse;
  9. /**
  10. * <p>
  11. * 登出业务逻辑类
  12. * </p>
  13. *
  14. * @author qy
  15. * @since 2019-11-08
  16. */
  17. public class TokenLogoutHandler implements LogoutHandler {
  18. private TokenManager tokenManager;
  19. private RedisTemplate redisTemplate;
  20. public TokenLogoutHandler(TokenManager tokenManager, RedisTemplate redisTemplate) {
  21. this.tokenManager = tokenManager;
  22. this.redisTemplate = redisTemplate;
  23. }
  24. @Override
  25. public void logout(HttpServletRequest request, HttpServletResponse response, Authentication authentication) {
  26. String token = request.getHeader("token");
  27. if (token != null) {
  28. tokenManager.removeToken(token);
  29. //清空当前用户缓存中的权限数据
  30. String userName = tokenManager.getUserFromToken(token);
  31. redisTemplate.delete(userName);
  32. }
  33. ResponseUtil.out(response, R.ok());
  34. }
  35. }

4.5token生成

  1. package com.atguigu.serurity.security;
  2. import io.jsonwebtoken.CompressionCodecs;
  3. import io.jsonwebtoken.Jwts;
  4. import io.jsonwebtoken.SignatureAlgorithm;
  5. import org.springframework.stereotype.Component;
  6. import java.util.Date;
  7. /**
  8. * <p>
  9. * token管理
  10. * </p>
  11. *
  12. * @author qy
  13. * @since 2019-11-08
  14. */
  15. @Component
  16. public class TokenManager {
  17. private long tokenExpiration = 24*60*60*1000;
  18. private String tokenSignKey = "123456";
  19. public String createToken(String username) {
  20. String token = Jwts.builder().setSubject(username)
  21. .setExpiration(new Date(System.currentTimeMillis() + tokenExpiration))
  22. .signWith(SignatureAlgorithm.HS512, tokenSignKey).compressWith(CompressionCodecs.GZIP).compact();
  23. return token;
  24. }
  25. public String getUserFromToken(String token) {
  26. String user = Jwts.parser().setSigningKey(tokenSignKey).parseClaimsJws(token).getBody().getSubject();
  27. return user;
  28. }
  29. public void removeToken(String token) {
  30. //jwttoken无需删除,客户端扔掉即可。
  31. }
  32. }

4.6未授权

  1. package com.atguigu.serurity.security;
  2. import com.atguigu.commonutils.R;
  3. import com.atguigu.commonutils.ResponseUtil;
  4. import org.springframework.security.core.AuthenticationException;
  5. import org.springframework.security.web.AuthenticationEntryPoint;
  6. import javax.servlet.ServletException;
  7. import javax.servlet.http.HttpServletRequest;
  8. import javax.servlet.http.HttpServletResponse;
  9. import java.io.IOException;
  10. /**
  11. * <p>
  12. * 未授权的统一处理方式
  13. * </p>
  14. *
  15. * @author qy
  16. * @since 2019-11-08
  17. */
  18. public class UnauthorizedEntryPoint implements AuthenticationEntryPoint {
  19. @Override
  20. public void commence(HttpServletRequest request, HttpServletResponse response,
  21. AuthenticationException authException) throws IOException, ServletException {
  22. ResponseUtil.out(response, R.error());
  23. }
  24. }

4.7 XML

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <project xmlns="http://maven.apache.org/POM/4.0.0"
  3. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  4. xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  5. <parent>
  6. <artifactId>commont</artifactId>
  7. <groupId>com.atguigu</groupId>
  8. <version>0.0.1-SNAPSHOT</version>
  9. </parent>
  10. <modelVersion>4.0.0</modelVersion>
  11. <artifactId>spring_security</artifactId>
  12. <dependencies>
  13. <dependency>
  14. <groupId>com.atguigu</groupId>
  15. <artifactId>comment_utils</artifactId>
  16. <version>0.0.1-SNAPSHOT</version>
  17. </dependency>
  18. <!-- Spring Security依赖 -->
  19. <dependency>
  20. <groupId>org.springframework.boot</groupId>
  21. <artifactId>spring-boot-starter-security</artifactId>
  22. </dependency>
  23. <dependency>
  24. <groupId>io.jsonwebtoken</groupId>
  25. <artifactId>jjwt</artifactId>
  26. </dependency>
  27. </dependencies>
  28. </project>
  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <project xmlns="http://maven.apache.org/POM/4.0.0"
  3. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  4. xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  5. <parent>
  6. <artifactId>guli_parent</artifactId>
  7. <groupId>com.atguigu</groupId>
  8. <version>0.0.1-SNAPSHOT</version>
  9. </parent>
  10. <modelVersion>4.0.0</modelVersion>
  11. <artifactId>commont</artifactId>
  12. <packaging>pom</packaging>
  13. <modules>
  14. <module>service_base</module>
  15. <module>comment_utils</module>
  16. <module>spring_security</module>
  17. </modules>
  18. <dependencies>
  19. <!-- redis -->
  20. <dependency>
  21. <groupId>org.springframework.boot</groupId>
  22. <artifactId>spring-boot-starter-data-redis</artifactId>
  23. </dependency>
  24. <!-- spring2.X集成redis所需common-pool2-->
  25. <dependency>
  26. <groupId>org.apache.commons</groupId>
  27. <artifactId>commons-pool2</artifactId>
  28. <version>2.6.0</version>
  29. </dependency>
  30. <dependency>
  31. <groupId>org.springframework.boot</groupId>
  32. <artifactId>spring-boot-starter-web</artifactId>
  33. <scope>provided </scope>
  34. </dependency>
  35. <!--mybatis-plus-->
  36. <dependency>
  37. <groupId>com.baomidou</groupId>
  38. <artifactId>mybatis-plus-boot-starter</artifactId>
  39. <scope>provided </scope>
  40. </dependency>
  41. <!--lombok用来简化实体类:需要安装lombok插件-->
  42. <dependency>
  43. <groupId>org.projectlombok</groupId>
  44. <artifactId>lombok</artifactId>
  45. <scope>provided </scope>
  46. </dependency>
  47. <!--swagger-->
  48. <dependency>
  49. <groupId>io.springfox</groupId>
  50. <artifactId>springfox-swagger2</artifactId>
  51. <scope>provided </scope>
  52. </dependency>
  53. <dependency>
  54. <groupId>io.springfox</groupId>
  55. <artifactId>springfox-swagger-ui</artifactId>
  56. <scope>provided </scope>
  57. </dependency>
  58. <!-- redis -->
  59. <dependency>
  60. <groupId>org.springframework.boot</groupId>
  61. <artifactId>spring-boot-starter-data-redis</artifactId>
  62. </dependency>
  63. <!-- spring2.X集成redis所需common-pool2
  64. <dependency>
  65. <groupId>org.apache.commons</groupId>
  66. <artifactId>commons-pool2</artifactId>
  67. <version>2.6.0</version>
  68. </dependency>-->
  69. </dependencies>
  70. </project>

4.7 jwt

  1. package com.atguigu.commonutils;
  2. import io.jsonwebtoken.Claims;
  3. import io.jsonwebtoken.Jws;
  4. import io.jsonwebtoken.Jwts;
  5. import io.jsonwebtoken.SignatureAlgorithm;
  6. import org.springframework.http.server.reactive.ServerHttpRequest;
  7. import org.springframework.util.StringUtils;
  8. import javax.servlet.http.HttpServletRequest;
  9. import java.util.Date;
  10. /**
  11. * @author helen
  12. * @since 2019/10/16
  13. * 生成字符串,包含用户信息,
  14. * jwt生成包含三部分:1头2.有效荷载3.签名哈希 防伪标志
  15. */
  16. public class JwtUtils {
  17. public static final long EXPIRE = 1000 * 60 * 60 * 24;//token过期时间
  18. public static final String APP_SECRET = "ukc8BDbRigUDaY6pZFfWus2jZWLPHO";//密钥
  19. public static String getJwtToken(String id, String nickname){
  20. String JwtToken = Jwts.builder()
  21. //第一步分
  22. .setHeaderParam("typ", "JWT")
  23. .setHeaderParam("alg", "HS256")
  24. //第二部分
  25. .setSubject("guli-user")
  26. .setIssuedAt(new Date())
  27. .setExpiration(new Date(System.currentTimeMillis() + EXPIRE))
  28. //第三部分 token主体
  29. .claim("id", id)
  30. .claim("nickname", nickname)
  31. .signWith(SignatureAlgorithm.HS256, APP_SECRET)
  32. .compact();
  33. return JwtToken;
  34. }
  35. /**
  36. * 判断token是否存在与有效
  37. * @param jwtToken
  38. * @return
  39. */
  40. public static boolean checkToken(String jwtToken) {
  41. if(StringUtils.isEmpty(jwtToken)) return false;
  42. try {
  43. Jwts.parser().setSigningKey(APP_SECRET).parseClaimsJws(jwtToken);
  44. } catch (Exception e) {
  45. e.printStackTrace();
  46. return false;
  47. }
  48. return true;
  49. }
  50. /**
  51. * 判断token是否存在与有效
  52. * @param request
  53. * @return
  54. */
  55. public static boolean checkToken(HttpServletRequest request) {
  56. try {
  57. String jwtToken = request.getHeader("token");
  58. System.out.println("jwtToken"+jwtToken);
  59. if(StringUtils.isEmpty(jwtToken)) return false;
  60. Jwts.parser().setSigningKey(APP_SECRET).parseClaimsJws(jwtToken);
  61. } catch (Exception e) {
  62. e.printStackTrace();
  63. return false;
  64. }
  65. return true;
  66. }
  67. /**
  68. * 根据token获取会员id
  69. * @param request
  70. * @return
  71. */
  72. public static String getMemberIdByJwtToken(HttpServletRequest request) {
  73. String jwtToken = request.getHeader("token");
  74. if(StringUtils.isEmpty(jwtToken))
  75. return "";
  76. Jws<Claims> claimsJws = Jwts.parser().setSigningKey(APP_SECRET).parseClaimsJws(jwtToken);
  77. Claims claims = claimsJws.getBody();
  78. System.out.println("claims:"+claims);
  79. return (String)claims.get("id");
  80. }
  81. }

4.8 MD5

  1. package com.atguigu.commonutils;
  2. import java.security.MessageDigest;
  3. import java.security.NoSuchAlgorithmException;
  4. public final class MD5 {
  5. public static String encrypt(String strSrc) {
  6. try {
  7. char hexChars[] = { '0', '1', '2', '3', '4', '5', '6', '7', '8',
  8. '9', 'a', 'b', 'c', 'd', 'e', 'f' };
  9. byte[] bytes = strSrc.getBytes();
  10. MessageDigest md = MessageDigest.getInstance("MD5");
  11. md.update(bytes);
  12. bytes = md.digest();
  13. System.out.println("bytes"+bytes);
  14. int j = bytes.length;
  15. System.out.println("j"+j);
  16. char[] chars = new char[j * 2];
  17. int k = 0;
  18. for (int i = 0; i < bytes.length; i++) {
  19. byte b = bytes[i];
  20. System.out.println(" bytes[i]"+ bytes[i]);
  21. //转化hexChars
  22. chars[k++] = hexChars[b >>> 4 & 0xf];
  23. chars[k++] = hexChars[b & 0xf];
  24. }
  25. return new String(chars);
  26. } catch (NoSuchAlgorithmException e) {
  27. e.printStackTrace();
  28. throw new RuntimeException("MD5加密出错!!+" + e);
  29. }
  30. }
  31. public static void main(String[] args) {
  32. System.out.println(MD5.encrypt("111111"));
  33. }
  34. }

4.9 R

  1. package com.atguigu.commonutils;
  2. import io.swagger.annotations.ApiModelProperty;
  3. import lombok.Data;
  4. import java.util.HashMap;
  5. import java.util.Map;
  6. @Data
  7. public class R {
  8. @ApiModelProperty(value = "是否成功")
  9. private Boolean success;
  10. @ApiModelProperty(value = "返回码")
  11. private Integer code;
  12. @ApiModelProperty(value = "返回消息")
  13. private String message;
  14. @ApiModelProperty(value = "返回数据")
  15. private Map<String, Object> data = new HashMap<String, Object>();
  16. //构造器私有化
  17. private R() {
  18. }
  19. //成功静态方法
  20. public static R ok() {
  21. R r = new R();
  22. r.setSuccess(true);
  23. r.setCode(ResultCode.SUCCESS);
  24. r.setMessage("成功");
  25. return r;
  26. }
  27. //失败静态方法
  28. public static R error() {
  29. R r = new R();
  30. r.setSuccess(false);
  31. r.setCode(ResultCode.ERROR);
  32. r.setMessage("失败");
  33. return r;
  34. }
  35. public R success(Boolean success) {
  36. this.setSuccess(success);
  37. return this;
  38. }
  39. public R message(String message) {
  40. this.setMessage(message);
  41. return this;
  42. }
  43. public R code(Integer code) {
  44. this.setCode(code);
  45. return this;
  46. }
  47. public R data(String key, Object value) {
  48. this.data.put(key, value);
  49. return this;
  50. }
  51. public R data(Map<String, Object> map) {
  52. this.setData(map);
  53. return this;
  54. }
  55. }

网站建设定制开发 软件系统开发定制 定制软件开发 软件开发定制 定制app开发 app开发定制 app开发定制公司 电商商城定制开发 定制小程序开发 定制开发小程序 客户管理系统开发定制 定制网站 定制开发 crm开发定制 开发公司 小程序开发定制 定制软件 收款定制开发 企业网站定制开发 定制化开发 android系统定制开发 定制小程序开发费用 定制设计 专注app软件定制开发 软件开发定制定制 知名网站建设定制 软件定制开发供应商 应用系统定制开发 软件系统定制开发 企业管理系统定制开发 系统定制开发