当前位置:   article > 正文

Gateway+Springsecurity+OAuth2.0+JWT 实现分布式统一认证授权!_spring cloud gateway + spring security oauth2 + jw

spring cloud gateway + spring security oauth2 + jwt

目录

1. OAuth2.0授权服务

2. 资源服务

3. Gateway网关

4. 测试


 

SpringSecurity+OAuth2.0 搭建认证中心和资源服务中心-CSDN博客 ​​​​​​

基础上整合网关和JWT实现分布式统一认证授权。

 

大致流程如下:

1、客户端发出请求给网关获取令牌

2、网关收到请求,直接转发给授权服务

3、授权服务验证用户名、密码等一系列身份,通过则颁发令牌给客户端

4、客户端携带令牌请求资源,请求直接到了网关层

5、网关对令牌进行校验(验签、过期时间校验....)、鉴权(对当前令牌携带的权限)和访问资源所需的权限进行比对,如果权限有交集则通过校验,直接转发给微服务

6、微服务进行逻辑处理

1. OAuth2.0授权服务

导入依赖

  1. <dependencies>
  2. <dependency>
  3. <groupId>org.springframework.boot</groupId>
  4. <artifactId>spring-boot-starter-web</artifactId>
  5. </dependency>
  6. <dependency>
  7. <groupId>org.springframework.cloud</groupId>
  8. <artifactId>spring-cloud-starter-security</artifactId>
  9. <version>2.2.5.RELEASE</version>
  10. </dependency>
  11. <dependency>
  12. <groupId>org.springframework.cloud</groupId>
  13. <artifactId>spring-cloud-starter-oauth2</artifactId>
  14. <version>2.2.5.RELEASE</version>
  15. </dependency>
  16. <dependency>
  17. <groupId>mysql</groupId>
  18. <artifactId>mysql-connector-java</artifactId>
  19. <version>8.0.28</version>
  20. </dependency>
  21. <dependency>
  22. <groupId>com.baomidou</groupId>
  23. <artifactId>mybatis-plus-boot-starter</artifactId>
  24. <version>3.3.2</version>
  25. </dependency>
  26. <dependency>
  27. <groupId>org.springframework.security</groupId>
  28. <artifactId>spring-security-oauth2-resource-server</artifactId>
  29. </dependency>
  30. <dependency>
  31. <groupId>org.projectlombok</groupId>
  32. <artifactId>lombok</artifactId>
  33. <version>1.18.30</version>
  34. </dependency>
  35. <dependency>
  36. <groupId>org.springframework.boot</groupId>
  37. <artifactId>spring-boot-starter-test</artifactId>
  38. </dependency>
  39. <dependency>
  40. <groupId>com.alibaba.cloud</groupId>
  41. <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
  42. </dependency>
  43. </dependencies>

application.yaml

  1. server:
  2. port: 8080
  3. spring:
  4. application:
  5. name: oauth2-cloud-auth-server
  6. cloud:
  7. nacos:
  8. ## 注册中心配置
  9. discovery:
  10. # nacos的服务地址,nacos-server中IP地址:端口号
  11. server-addr: 127.0.0.1:8848
  12. datasource:
  13. driver-class-name: com.mysql.cj.jdbc.Driver
  14. url: jdbc:mysql://localhost:3306/rbac?useUnicode=true&characterEncoding=UTF-8&serverTimezone=UTC
  15. username: root
  16. password: 123456

 这里展示部分代码

AccessTokenConfig类

  1. /**
  2. * 令牌的配置
  3. */
  4. @Configuration
  5. public class AccessTokenConfig {
  6. /**
  7. * JWT的秘钥
  8. * TODO 实际项目中需要统一配置到配置文件中,资源服务也需要用到
  9. */
  10. private final static String SIGN_KEY="jwt";
  11. /**
  12. * 令牌的存储策略
  13. */
  14. @Bean
  15. public TokenStore tokenStore() {
  16. //使用JwtTokenStore生成JWT令牌
  17. return new JwtTokenStore(jwtAccessTokenConverter());
  18. }
  19. /**
  20. * JwtAccessTokenConverter
  21. * TokenEnhancer的子类,在JWT编码的令牌值和OAuth身份验证信息之间进行转换。
  22. * TODO:后期可以使用非对称加密
  23. */
  24. @Bean
  25. public JwtAccessTokenConverter jwtAccessTokenConverter(){
  26. JwtAccessTokenConverter converter = new JwtAccessTokenConverter();
  27. // 设置秘钥
  28. converter.setSigningKey(SIGN_KEY);
  29. return converter;
  30. }
  31. @Bean
  32. PasswordEncoder passwordEncoder() {
  33. return new BCryptPasswordEncoder();
  34. }
  35. }

MyAuthorizationConfig类

  1. @Configuration
  2. @EnableAuthorizationServer
  3. public class MyAuthorizationConfig extends AuthorizationServerConfigurerAdapter {
  4. @Autowired
  5. private TokenStore tokenStore;
  6. /**
  7. * 客户端存储策略,这里使用内存方式,后续可以存储在数据库
  8. */
  9. @Autowired
  10. private ClientDetailsService clientDetailsService;
  11. /**
  12. * Security的认证管理器,密码模式需要用到
  13. */
  14. @Autowired
  15. private AuthenticationManager authenticationManager;
  16. @Autowired
  17. private JwtAccessTokenConverter jwtAccessTokenConverter;
  18. /**
  19. * 配置令牌访问的安全约束
  20. */
  21. @Override
  22. public void configure(AuthorizationServerSecurityConfigurer security) throws Exception {
  23. security
  24. //开启/oauth/token_key验证端口权限访问
  25. .tokenKeyAccess("permitAll()")
  26. //开启/oauth/check_token验证端口认证权限访问
  27. .checkTokenAccess("permitAll()")
  28. //表示支持 client_id 和 client_secret 做登录认证
  29. .allowFormAuthenticationForClients();
  30. }
  31. //配置客户端
  32. @Override
  33. public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
  34. //内存模式
  35. clients.inMemory()
  36. //客户端id
  37. .withClient("test")
  38. //客户端秘钥
  39. .secret(new BCryptPasswordEncoder().encode("123456"))
  40. //资源id,唯一,比如订单服务作为一个资源,可以设置多个
  41. .resourceIds("order")
  42. //授权模式,总共四种,1. authorization_code(授权码模式)、password(密码模式)、client_credentials(客户端模式)、implicit(简化模式)
  43. //refresh_token并不是授权模式,
  44. .authorizedGrantTypes("authorization_code","password","client_credentials","implicit","refresh_token")
  45. //允许的授权范围,客户端的权限,这里的all只是一种标识,可以自定义,为了后续的资源服务进行权限控制
  46. .scopes("all")
  47. //false 则跳转到授权页面
  48. .autoApprove(false)
  49. //授权码模式的回调地址
  50. .redirectUris("http://www.baidu.com"); //可以and继续添加客户端
  51. }
  52. @Bean
  53. public AuthorizationServerTokenServices tokenServices() {
  54. DefaultTokenServices services = new DefaultTokenServices();
  55. //客户端端配置策略
  56. services.setClientDetailsService(clientDetailsService);
  57. //支持令牌的刷新
  58. services.setSupportRefreshToken(true);
  59. //令牌服务
  60. services.setTokenStore(tokenStore);
  61. //access_token的过期时间
  62. services.setAccessTokenValiditySeconds(60 * 60 * 2);
  63. //refresh_token的过期时间
  64. services.setRefreshTokenValiditySeconds(60 * 60 * 24 * 3);
  65. //设置令牌增强,使用jwt
  66. services.setTokenEnhancer(jwtAccessTokenConverter);
  67. return services;
  68. }
  69. /**
  70. * 授权码模式的service,使用授权码模式authorization_code必须注入
  71. */
  72. @Bean
  73. public AuthorizationCodeServices authorizationCodeServices() {
  74. //授权码存在内存中
  75. return new InMemoryAuthorizationCodeServices();
  76. }
  77. /**
  78. * 配置令牌访问的端点
  79. */
  80. @Override
  81. public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
  82. endpoints
  83. //授权码模式所需要的authorizationCodeServices
  84. .authorizationCodeServices(authorizationCodeServices())
  85. //密码模式所需要的authenticationManager
  86. .authenticationManager(authenticationManager)
  87. //令牌管理服务,无论哪种模式都需要
  88. .tokenServices(tokenServices())
  89. //只允许POST提交访问令牌,uri:/oauth/token
  90. .allowedTokenEndpointRequestMethods(HttpMethod.POST);
  91. }
  92. }

SecurityConfig类

  1. /**
  2. * spring security的安全配置
  3. */
  4. @Configuration
  5. @EnableWebSecurity
  6. public class SecurityConfig extends WebSecurityConfigurerAdapter {
  7. /**
  8. * 加密算法
  9. */
  10. @Autowired
  11. JwtTokenUserDetailsService userDetailsService;
  12. @Override
  13. protected void configure(HttpSecurity http) throws Exception {
  14. //todo 允许表单登录
  15. http.authorizeRequests()
  16. .anyRequest().authenticated()
  17. .and()
  18. .formLogin()
  19. .loginProcessingUrl("/login")
  20. .permitAll()
  21. .and()
  22. .csrf()
  23. .disable();
  24. }
  25. @Override
  26. protected void configure(AuthenticationManagerBuilder auth) throws Exception {
  27. //从数据库中查询用户信息
  28. auth.userDetailsService(userDetailsService);
  29. }
  30. /**
  31. * AuthenticationManager对象在OAuth2认证服务中要使用,提前放入IOC容器中
  32. * Oauth的密码模式需要
  33. */
  34. @Override
  35. @Bean
  36. public AuthenticationManager authenticationManagerBean() throws Exception {
  37. return super.authenticationManagerBean();
  38. }
  39. }

2. 资源服务

导入依赖

  1. <dependency>
  2. <groupId>org.springframework.boot</groupId>
  3. <artifactId>spring-boot-starter-web</artifactId>
  4. </dependency>
  5. <dependency>
  6. <groupId>cn.hutool</groupId>
  7. <artifactId>hutool-all</artifactId>
  8. </dependency>
  9. <dependency>
  10. <groupId>com.alibaba</groupId>
  11. <artifactId>fastjson</artifactId>
  12. <version>1.2.78</version>
  13. </dependency>
  14. <dependency>
  15. <groupId>org.projectlombok</groupId>
  16. <artifactId>lombok</artifactId>
  17. <version>1.18.30</version>
  18. </dependency>
  19. <dependency>
  20. <groupId>com.alibaba.cloud</groupId>
  21. <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
  22. </dependency>

application.yaml

  1. server:
  2. port: 8081
  3. spring:
  4. application:
  5. name: oauth2-cloud-service
  6. cloud:
  7. nacos:
  8. ## 注册中心配置
  9. discovery:
  10. # nacos的服务地址,nacos-server中IP地址:端口号
  11. server-addr: 127.0.0.1:8848

 AuthenticationFilter类

  1. @Component
  2. public class AuthenticationFilter extends OncePerRequestFilter {
  3. /**
  4. * 具体方法主要分为两步
  5. * 1. 解密网关传递的信息
  6. * 2. 将解密之后的信息封装放入到request中
  7. */
  8. @Override
  9. protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
  10. //获取请求头中的用户信息
  11. String token = request.getHeader("token");
  12. if (token!=null){
  13. //解密
  14. String json = Base64.decodeStr(token);
  15. JSONObject jsonObject = JSON.parseObject(json);
  16. //获取用户身份信息、权限信息
  17. String principal = jsonObject.getString("user_name");
  18. JSONArray tempJsonArray = jsonObject.getJSONArray("authorities");
  19. //权限
  20. String[] authorities = tempJsonArray.toArray(new String[0]);
  21. //放入LoginVal
  22. LoginVal loginVal = new LoginVal();
  23. loginVal.setUsername(principal);
  24. loginVal.setAuthorities(authorities);
  25. //放入request的attribute中
  26. request.setAttribute("login_message",loginVal);
  27. }
  28. filterChain.doFilter(request,response);
  29. }
  30. }

ServiceController类

  1. @RestController
  2. public class ServiceController {
  3. @RequestMapping("/test")
  4. public LoginVal test(HttpServletRequest httpServletRequest){
  5. return (LoginVal)httpServletRequest.getAttribute("login_message");
  6. }
  7. }

3. Gateway网关

导入依赖

  1. <dependencies>
  2. <dependency>
  3. <groupId>org.springframework.cloud</groupId>
  4. <artifactId>spring-cloud-starter-gateway</artifactId>
  5. </dependency>
  6. <dependency>
  7. <groupId>org.springframework.cloud</groupId>
  8. <artifactId>spring-cloud-starter-security</artifactId>
  9. <version>2.2.5.RELEASE</version>
  10. </dependency>
  11. <dependency>
  12. <groupId>org.springframework.cloud</groupId>
  13. <artifactId>spring-cloud-starter-oauth2</artifactId>
  14. <version>2.2.5.RELEASE</version>
  15. </dependency>
  16. <dependency>
  17. <groupId>org.springframework.security</groupId>
  18. <artifactId>spring-security-oauth2-resource-server</artifactId>
  19. </dependency>
  20. <dependency>
  21. <groupId>com.alibaba.cloud</groupId>
  22. <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
  23. </dependency>
  24. <dependency>
  25. <groupId>org.projectlombok</groupId>
  26. <artifactId>lombok</artifactId>
  27. </dependency>
  28. <dependency>
  29. <groupId>cn.hutool</groupId>
  30. <artifactId>hutool-all</artifactId>
  31. </dependency>
  32. <dependency>
  33. <groupId>com.alibaba</groupId>
  34. <artifactId>fastjson</artifactId>
  35. <version>1.2.78</version>
  36. </dependency>
  37. <dependency>
  38. <groupId>org.springframework.cloud</groupId>
  39. <artifactId>spring-cloud-starter-loadbalancer</artifactId>
  40. </dependency>
  41. </dependencies>

application.yaml

  1. server:
  2. port: 7000
  3. spring:
  4. main:
  5. allow-bean-definition-overriding: true
  6. application:
  7. name: oauth2-cloud-gateway
  8. cloud:
  9. nacos:
  10. ## 注册中心配置
  11. discovery:
  12. # nacos的服务地址,nacos-server中IP地址:端口号
  13. server-addr: 127.0.0.1:8848
  14. gateway:
  15. ## 路由
  16. routes:
  17. ## id只要唯一即可,名称任意
  18. - id: oauth2-cloud-auth-server
  19. uri: lb://oauth2-cloud-auth-server
  20. predicates:
  21. ## Path Route Predicate Factory断言
  22. - Path=/oauth/**
  23. - id: oauth2-cloud-order
  24. uri: lb://oauth2-cloud-service
  25. predicates:
  26. ## Path Route Predicate Factory断言
  27. - Path=/test/**
  28. oauth2:
  29. cloud:
  30. sys:
  31. parameter:
  32. ignoreUrls:
  33. - /oauth/token
  34. - /oauth/authorize

 AccessTokenConfig类

  1. /**
  2. * 令牌的配置
  3. */
  4. @Configuration
  5. public class AccessTokenConfig {
  6. private final static String SIGN_KEY="jwt";
  7. /**
  8. * 令牌的存储策略
  9. */
  10. @Bean
  11. public TokenStore tokenStore() {
  12. //使用JwtTokenStore生成JWT令牌
  13. return new JwtTokenStore(jwtAccessTokenConverter());
  14. }
  15. /**
  16. * JwtAccessTokenConverter
  17. * TokenEnhancer的子类,在JWT编码的令牌值和OAuth身份验证信息之间进行转换。
  18. * TODO:后期可以使用非对称加密
  19. */
  20. @Bean
  21. public JwtAccessTokenConverter jwtAccessTokenConverter(){
  22. JwtAccessTokenConverter converter = new JwtAccessTokenConverter();
  23. // 设置秘钥
  24. converter.setSigningKey(SIGN_KEY);
  25. return converter;
  26. }
  27. }

JwtAccessManager类

  1. @Slf4j
  2. @Component
  3. //经过认证管理器JwtAuthenticationManager认证成功后,就需要对令牌进行鉴权,如果该令牌无访问资源的权限,则不允通过。
  4. public class JwtAccessManager implements ReactiveAuthorizationManager<AuthorizationContext> {
  5. @Override
  6. public Mono<AuthorizationDecision> check(Mono<Authentication> mono, AuthorizationContext authorizationContext) {
  7. URI uri = authorizationContext.getExchange().getRequest().getURI();
  8. //设计权限角色,这里简单写一下,实际上应该从数据库或者缓存中获取
  9. List<String> authorities = new ArrayList<>();
  10. authorities.add("ROLE_admin");
  11. //认证通过且角色匹配的用户可访问当前路径
  12. return mono
  13. //判断是否认证成功
  14. .filter(Authentication::isAuthenticated)
  15. //获取认证后的全部权限
  16. .flatMapIterable(Authentication::getAuthorities)
  17. .map(GrantedAuthority::getAuthority)
  18. //如果权限包含则判断为true
  19. .any(authorities::contains)
  20. .map(AuthorizationDecision::new)
  21. .defaultIfEmpty(new AuthorizationDecision(false));
  22. }
  23. }

JwtAuthenticationManager类

  1. /**
  2. * JWT认证管理器,主要的作用就是对携带过来的token进行校验,比如过期时间,加密方式等
  3. * 一旦token校验通过,则交给鉴权管理器进行鉴权
  4. */
  5. @Component
  6. public class JwtAuthenticationManager implements ReactiveAuthenticationManager {
  7. /**
  8. * 使用JWT令牌进行解析令牌
  9. */
  10. @Autowired
  11. private TokenStore tokenStore;
  12. @Override
  13. public Mono<Authentication> authenticate(Authentication authentication) {
  14. return Mono.justOrEmpty(authentication)
  15. .filter(a -> a instanceof BearerTokenAuthenticationToken)
  16. .cast(BearerTokenAuthenticationToken.class)
  17. .map(BearerTokenAuthenticationToken::getToken)
  18. .flatMap((accessToken -> {
  19. OAuth2AccessToken oAuth2AccessToken = this.tokenStore.readAccessToken(accessToken);
  20. //根据access_token从数据库获取不到OAuth2AccessToken
  21. if (oAuth2AccessToken == null) {
  22. return Mono.error(new InvalidTokenException("无效的token!"));
  23. } else if (oAuth2AccessToken.isExpired()) {
  24. return Mono.error(new InvalidTokenException("token已过期!"));
  25. }
  26. OAuth2Authentication oAuth2Authentication = this.tokenStore.readAuthentication(accessToken);
  27. if (oAuth2Authentication == null) {
  28. return Mono.error(new InvalidTokenException("无效的token!"));
  29. } else {
  30. return Mono.just(oAuth2Authentication);
  31. }
  32. })).cast(Authentication.class);
  33. }
  34. }

SecurityConfig类

  1. @Configuration
  2. @EnableWebFluxSecurity
  3. public class SecurityConfig {
  4. /**
  5. * JWT的鉴权管理器
  6. */
  7. @Autowired
  8. private ReactiveAuthorizationManager<AuthorizationContext> accessManager;
  9. @Autowired
  10. private RequestAuthenticationEntryPoint requestAuthenticationEntryPoint;
  11. @Autowired
  12. private RequestAccessDeniedHandler requestAccessDeniedHandler;
  13. /**
  14. * 系统参数配置
  15. */
  16. @Autowired
  17. private SysParameterConfig sysConfig;
  18. /**
  19. * token校验管理器
  20. */
  21. @Autowired
  22. private ReactiveAuthenticationManager tokenAuthenticationManager;
  23. @Autowired
  24. private CorsFilter corsFilter;
  25. @Bean
  26. SecurityWebFilterChain webFluxSecurityFilterChain(ServerHttpSecurity http) throws Exception{
  27. //认证过滤器,放入认证管理器tokenAuthenticationManager
  28. AuthenticationWebFilter authenticationWebFilter = new AuthenticationWebFilter(tokenAuthenticationManager);
  29. authenticationWebFilter.setServerAuthenticationConverter(new ServerBearerTokenAuthenticationConverter());
  30. http
  31. .httpBasic().disable()
  32. .csrf().disable()
  33. .authorizeExchange()
  34. //白名单直接放行
  35. .pathMatchers(ArrayUtil.toArray(sysConfig.getIgnoreUrls(),String.class)).permitAll()
  36. //其他的请求必须鉴权,使用鉴权管理器
  37. .anyExchange().access(accessManager)
  38. //异常处理
  39. .and().exceptionHandling()
  40. .authenticationEntryPoint(requestAuthenticationEntryPoint)
  41. .accessDeniedHandler(requestAccessDeniedHandler)
  42. .and()
  43. // 跨域过滤器
  44. .addFilterAt(corsFilter, SecurityWebFiltersOrder.CORS)
  45. //token的认证过滤器,用于校验token和认证
  46. .addFilterAt(authenticationWebFilter, SecurityWebFiltersOrder.AUTHENTICATION);
  47. return http.build();
  48. }
  49. }

RequestAccessDeniedHandler

  1. /**
  2. * 自定义返回结果:没有权限访问时
  3. */
  4. @Component
  5. public class RequestAccessDeniedHandler implements ServerAccessDeniedHandler {
  6. @Override
  7. public Mono<Void> handle(ServerWebExchange exchange, AccessDeniedException denied) {
  8. ServerHttpResponse response = exchange.getResponse();
  9. response.setStatusCode(HttpStatus.OK);
  10. response.getHeaders().add(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE);
  11. String body= JSONUtil.toJsonStr(new ResultMsg(1005,"无权限访问",null));
  12. DataBuffer buffer = response.bufferFactory().wrap(body.getBytes(Charset.forName("UTF-8")));
  13. return response.writeWith(Mono.just(buffer));
  14. }
  15. }

GlobalAuthenticationFilter

  1. /**
  2. * 全局过滤器,对token的拦截,解析token放入header中,便于下游微服务获取用户信息
  3. * 分为如下几步:
  4. * 1、白名单直接放行
  5. * 2、校验token
  6. * 3、读取token中存放的用户信息
  7. * 4、重新封装用户信息,加密成功json数据放入请求头中传递给下游微服务
  8. */
  9. @Component
  10. @Slf4j
  11. public class GlobalAuthenticationFilter implements GlobalFilter, Ordered {
  12. /**
  13. * JWT令牌的服务
  14. */
  15. @Autowired
  16. private TokenStore tokenStore;
  17. /**
  18. * 系统参数配置
  19. */
  20. @Autowired
  21. private SysParameterConfig sysConfig;
  22. @Override
  23. public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
  24. String requestUrl = exchange.getRequest().getPath().value();
  25. //1、白名单放行,比如授权服务、静态资源.....
  26. if (checkUrls(sysConfig.getIgnoreUrls(),requestUrl)){
  27. return chain.filter(exchange);
  28. }
  29. //2、 检查token是否存在
  30. String token = getToken(exchange);
  31. if (StringUtils.isBlank(token)) {
  32. return invalidTokenMono(exchange);
  33. }
  34. //3 判断是否是有效的token
  35. OAuth2AccessToken oAuth2AccessToken;
  36. try {
  37. //解析token,使用tokenStore
  38. oAuth2AccessToken = tokenStore.readAccessToken(token);
  39. Map<String, Object> additionalInformation = oAuth2AccessToken.getAdditionalInformation();
  40. System.out.println(additionalInformation);
  41. //取出用户身份信息
  42. String user_name = additionalInformation.get("user_name").toString();
  43. //获取用户权限
  44. List<String> authorities = (List<String>) additionalInformation.get("authorities");
  45. //将用户名和权限进行Base64加密
  46. JSONObject jsonObject=new JSONObject();
  47. jsonObject.put("user_name", user_name);
  48. jsonObject.put("authorities",authorities);
  49. String base = Base64.encode(jsonObject.toJSONString());
  50. // ServerHttpRequest 中的 mutate 方法是用于创建一个修改后的请求对象的方法,而不改变原始请求对象。这个方法是为了在处理请求过程中创建一个新的请求对象,以便进行一些修改或增强。
  51. ServerHttpRequest tokenRequest = exchange.getRequest().mutate().header("token",base).build();
  52. ServerWebExchange build = exchange.mutate().request(tokenRequest).build();
  53. return chain.filter(build);
  54. } catch (InvalidTokenException e) {
  55. //解析token异常,直接返回token无效
  56. return invalidTokenMono(exchange);
  57. }
  58. }
  59. @Override
  60. public int getOrder() {
  61. return 0;
  62. }
  63. /**
  64. * 对url进行校验匹配
  65. */
  66. private boolean checkUrls(List<String> urls,String path){
  67. AntPathMatcher pathMatcher = new AntPathMatcher();
  68. for (String url : urls) {
  69. if (pathMatcher.match(url,path))
  70. return true;
  71. }
  72. return false;
  73. }
  74. /**
  75. * 从请求头中获取Token
  76. */
  77. private String getToken(ServerWebExchange exchange) {
  78. String tokenStr = exchange.getRequest().getHeaders().getFirst("Authorization");
  79. if (StringUtils.isBlank(tokenStr)) {
  80. return null;
  81. }
  82. String token = tokenStr.split(" ")[1];
  83. if (StringUtils.isBlank(token)) {
  84. return null;
  85. }
  86. return token;
  87. }
  88. /**
  89. * 无效的token
  90. */
  91. private Mono<Void> invalidTokenMono(ServerWebExchange exchange) {
  92. return buildReturnMono(ResultMsg.builder()
  93. .code(1004)
  94. .msg("无效的token")
  95. .build(), exchange);
  96. }
  97. private Mono<Void> buildReturnMono(ResultMsg resultMsg, ServerWebExchange exchange) {
  98. ServerHttpResponse response = exchange.getResponse();
  99. byte[] bits = JSON.toJSONString(resultMsg).getBytes(StandardCharsets.UTF_8);
  100. DataBuffer buffer = response.bufferFactory().wrap(bits);
  101. response.setStatusCode(HttpStatus.UNAUTHORIZED);
  102. response.getHeaders().add("Content-Type", "application/json;charset:utf-8");
  103. return response.writeWith(Mono.just(buffer));
  104. }
  105. }

SysParameterConfig

  1. @ConfigurationProperties(prefix = "oauth2.cloud.sys.parameter")
  2. @Data
  3. @Component
  4. public class SysParameterConfig {
  5. /**
  6. * 白名单
  7. */
  8. private List<String> ignoreUrls;
  9. }

4. 测试

 

代码链接:Gateway+Springsecurity+OAuth2.0+JWT实现分布式统一认证授权资源-CSDN文库 

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

闽ICP备14008679号