当前位置:   article > 正文

全网最全的微服务+Outh2套餐,Gateway整合Oauth2!(入门到精通,附源码)满足你的味蕾需要(三)

gateway整合oauth2

上篇文章主要讲解Oauth2模块、user-service模块、feign模块,那么作为重中之重的gateway,我们将其做成资源服务器来进行开发。

一、资源服务器的实现方式

资源服务器在实际开发有两种实现方式:

(1)gateway做网关转发,不做资源服务器,由各个微服务模块自己去做资源服务器;

(2)gateway做网关转发 并且 资源服务器

前者方案使得每一个微服务模块都需要导入oauth2相关依赖,并且做处理,过于繁琐且耦合高。

所以本文章在接下来介绍,也就是文章的重点,并且会介绍到如何解决通过gateway去认证授权,跳转到oauth2认证授权后,跳转不回或重定向不到gatway的bug。

二、gateway模块

 1、模块结构

2、pom

  1. <dependencies>
  2. <dependency>
  3. <groupId>cn.hutool</groupId>
  4. <artifactId>hutool-all</artifactId>
  5. </dependency>
  6. <dependency>
  7. <groupId>org.springframework.security</groupId>
  8. <artifactId>spring-security-oauth2-jose</artifactId>
  9. </dependency>
  10. <dependency>
  11. <groupId>org.springframework.security</groupId>
  12. <artifactId>spring-security-oauth2-resource-server</artifactId>
  13. </dependency>
  14. <dependency>
  15. <groupId>org.springframework.boot</groupId>
  16. <artifactId>spring-boot-starter-web</artifactId>
  17. </dependency>
  18. <dependency>
  19. <groupId>org.springframework.cloud</groupId>
  20. <artifactId>spring-cloud-starter-oauth2</artifactId>
  21. </dependency>
  22. <dependency>
  23. <groupId>org.springframework.cloud</groupId>
  24. <artifactId>spring-cloud-starter-gateway</artifactId>
  25. </dependency>
  26. <dependency>
  27. <groupId>com.alibaba.cloud</groupId>
  28. <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
  29. </dependency>
  30. <!--加载bootstrap 文件-->
  31. <dependency>
  32. <groupId>org.springframework.cloud</groupId>
  33. <artifactId>spring-cloud-starter-bootstrap</artifactId>
  34. </dependency>
  35. <!--客户端负载均衡loadbalancer-->
  36. <dependency>
  37. <groupId>org.springframework.cloud</groupId>
  38. <artifactId>spring-cloud-starter-loadbalancer</artifactId>
  39. </dependency>
  40. <dependency>
  41. <groupId>org.projectlombok</groupId>
  42. <artifactId>lombok</artifactId>
  43. </dependency>
  44. <dependency>
  45. <groupId>com.white</groupId>
  46. <artifactId>common</artifactId>
  47. <version>1.0</version>
  48. <scope>compile</scope>
  49. </dependency>
  50. </dependencies>

3、bootstrap

  1. server:
  2. port: 10000
  3. spring:
  4. application:
  5. name: gateway
  6. profiles:
  7. active: dev
  8. cloud:
  9. gateway:
  10. routes:
  11. - id: user
  12. uri: lb://user-service # 客户端负载均衡 loadbalancer
  13. predicates:
  14. - Path=/user/**,/admin/**
  15. - id: order
  16. uri: lb://order-service
  17. predicates:
  18. - Path=/order/**
  19. - id: oauth
  20. uri: lb://oauth-service
  21. predicates:
  22. - Path=/uaa/**
  23. nacos:
  24. discovery:
  25. server-addr: localhost:8848
  26. redis:
  27. host: 127.0.0.1
  28. port: 6379
  29. security:
  30. oauth2:
  31. resourceserver:
  32. jwt:
  33. #配置RSA的公钥访问地址 端口对应上篇文章的oauth2模块服务的端口
  34. jwk-set-uri: 'http://localhost:8101/uaa/rsa/publicKey'
  35. main:
  36. web-application-type: reactive

4.GatewayApp启动类

  1. @SpringBootApplication(exclude= {DataSourceAutoConfiguration.class})
  2. @EnableGlobalMethodSecurity(prePostEnabled = true)
  3. public class GatewayApp
  4. {
  5. public static void main( String[] args )
  6. {
  7. SpringApplication.run(GatewayApp.class,args);
  8. }
  9. }

5.IgnoreUrlsConfig

  1. package com.white.gateway.config;
  2. import org.springframework.stereotype.Component;
  3. import java.util.ArrayList;
  4. import java.util.List;
  5. @Component
  6. public class IgnoreUrlsConfig {
  7. public List<String> getUrls() {
  8. ArrayList<String> objects = new ArrayList<>();
  9. objects.add("/uaa/**");
  10. objects.add("/user/**");
  11. return objects;
  12. }
  13. }

6.IgnoreUrlsRemoveJwtFilter

  1. package com.white.gateway.filter;
  2. import com.white.gateway.config.IgnoreUrlsConfig;
  3. import org.springframework.beans.factory.annotation.Autowired;
  4. import org.springframework.http.server.reactive.ServerHttpRequest;
  5. import org.springframework.stereotype.Component;
  6. import org.springframework.util.AntPathMatcher;
  7. import org.springframework.util.PathMatcher;
  8. import org.springframework.web.server.ServerWebExchange;
  9. import org.springframework.web.server.WebFilter;
  10. import org.springframework.web.server.WebFilterChain;
  11. import reactor.core.publisher.Mono;
  12. import var.TokenVar;
  13. import java.net.URI;
  14. import java.util.List;
  15. /**
  16. * 白名单路径访问时需要移除JWT请求头
  17. */
  18. @Component
  19. public class IgnoreUrlsRemoveJwtFilter implements WebFilter {
  20. @Autowired
  21. private IgnoreUrlsConfig ignoreUrlsConfig;
  22. @Override
  23. public Mono<Void> filter(ServerWebExchange exchange, WebFilterChain chain) {
  24. ServerHttpRequest request = exchange.getRequest();
  25. URI uri = request.getURI();
  26. PathMatcher pathMatcher = new AntPathMatcher();
  27. //白名单路径移除JWT请求头
  28. List<String> ignoreUrls = ignoreUrlsConfig.getUrls();
  29. for (String ignoreUrl : ignoreUrls) {
  30. if (pathMatcher.match(ignoreUrl, uri.getPath())) {
  31. request = request.mutate().header(TokenVar.TOKEN_HEAD, "").build();
  32. exchange = exchange.mutate().request(request).build();
  33. return chain.filter(exchange);
  34. }
  35. }
  36. return chain.filter(exchange);
  37. }
  38. }

7.AuthGlobalFilter

注意:这里拦截了路径为/oauth/authorize,在其进行跳转的时候构建响应包装类,解决通过gateway去oauth认证时,oauth成功登录后跳转不回gateway网关的bug。

  1. package com.white.gateway.filter;
  2. import cn.hutool.core.util.StrUtil;
  3. import cn.hutool.json.JSONUtil;
  4. import cn.hutool.json.JSONObject;
  5. import com.alibaba.cloud.commons.lang.StringUtils;
  6. import com.nimbusds.jose.JWSObject;
  7. import org.reactivestreams.Publisher;
  8. import org.springframework.beans.factory.annotation.Autowired;
  9. import org.springframework.cloud.gateway.filter.GatewayFilterChain;
  10. import org.springframework.cloud.gateway.filter.GlobalFilter;
  11. import org.springframework.cloud.gateway.filter.NettyWriteResponseFilter;
  12. import org.springframework.core.Ordered;
  13. import org.springframework.core.io.buffer.DataBuffer;
  14. import org.springframework.data.redis.core.RedisTemplate;
  15. import org.springframework.http.HttpStatus;
  16. import org.springframework.http.server.reactive.ServerHttpRequest;
  17. import org.springframework.http.server.reactive.ServerHttpResponse;
  18. import org.springframework.http.server.reactive.ServerHttpResponseDecorator;
  19. import org.springframework.stereotype.Component;
  20. import org.springframework.web.server.ServerWebExchange;
  21. import reactor.core.publisher.Mono;
  22. import var.TokenVar;
  23. import java.text.ParseException;
  24. import java.util.Objects;
  25. /**
  26. * 将登录用户的JWT转化成用户信息的全局过滤器
  27. */
  28. @Component
  29. public class AuthGlobalFilter implements GlobalFilter, Ordered {
  30. @Autowired
  31. private RedisTemplate redisTemplate;
  32. @Override
  33. public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
  34. //TODO
  35. String path = exchange.getRequest().getPath().value();
  36. System.out.println("拦截到的路径:::" + path);
  37. if (path.contains("/oauth/authorize") || path.contains("/auth/authorize") || path.contains("/auth/loginBySms")) {
  38. //构建响应包装类
  39. HttpResponseDecorator responseDecorator = new HttpResponseDecorator(exchange.getRequest(), exchange.getResponse(), "http://localhost:10000");
  40. return chain
  41. .filter(exchange.mutate().response(responseDecorator).build());
  42. }
  43. //认证信息从Header 或 请求参数 中获取
  44. ServerHttpRequest serverHttpRequest = exchange.getRequest();
  45. String token = serverHttpRequest.getHeaders().getFirst(TokenVar.TOKEN_HEAD);
  46. if (Objects.isNull(token)) {
  47. token = serverHttpRequest.getQueryParams().getFirst(TokenVar.TOKEN_HEAD);
  48. }
  49. if (StrUtil.isEmpty(token)) {
  50. return chain.filter(exchange);
  51. }
  52. try {
  53. //从token中解析用户信息并设置到Header中去
  54. String realToken = token.replace(TokenVar.TOKEN_PREFIX, "");
  55. JWSObject jwsObject = JWSObject.parse(realToken);
  56. String userStr = jwsObject.getPayload().toString();
  57. // 黑名单token(登出、修改密码)校验
  58. JSONObject jsonObject = JSONUtil.parseObj(userStr);
  59. String jti = jsonObject.getStr("jti");
  60. Boolean isBlack = redisTemplate.hasKey(TokenVar.TOKEN_BLACKLIST_PREFIX + jti);
  61. if (isBlack) {
  62. }
  63. // 存在token且不是黑名单,request写入JWT的载体信息
  64. ServerHttpRequest request = serverHttpRequest.mutate().header(TokenVar.USER_TOKEN_HEADER, userStr).build();
  65. exchange = exchange.mutate().request(request).build();
  66. } catch (ParseException e) {
  67. e.printStackTrace();
  68. }
  69. return chain.filter(exchange);
  70. }
  71. public class HttpResponseDecorator extends ServerHttpResponseDecorator {
  72. private String proxyUrl;
  73. private ServerHttpRequest request;
  74. public HttpResponseDecorator(ServerHttpRequest request, ServerHttpResponse delegate, String proxyUrl) {
  75. super(delegate);
  76. this.request = request;
  77. this.proxyUrl = proxyUrl;
  78. }
  79. @Override
  80. public Mono<Void> writeWith(Publisher<? extends DataBuffer> body) {
  81. HttpStatus status = this.getStatusCode();
  82. if (status.equals(HttpStatus.FOUND)) {
  83. String domain = "";
  84. if (StringUtils.isBlank(proxyUrl)) {
  85. domain = request.getURI().getScheme() + "://" + request.getURI().getAuthority();
  86. } else {
  87. domain = proxyUrl;
  88. }
  89. String location = getHeaders().getFirst("Location");
  90. String replaceLocation = location.replaceAll("^((ht|f)tps?):\\/\\/(\\d{1,3}.){3}\\d{1,3}(:\\d+)?", domain);
  91. getHeaders().set("Location", replaceLocation);
  92. }
  93. this.getStatusCode();
  94. return super.writeWith(body);
  95. }
  96. }
  97. @Override
  98. public int getOrder() {
  99. return NettyWriteResponseFilter.WRITE_RESPONSE_FILTER_ORDER - 1;
  100. }
  101. }

8.ResourceServerManager

注意:这里的鉴权采用了对redis数据进行读取后,匹配当前的路径和请求方式是否与redis数据中一致,在此前提下判断当前的token是否与redis中存放的身份权限一致或包含其中,如果包含或一致才可以放行去请求资源,否则请求资源失败。

至于redis的数据从哪来,下面程序中是模拟添加了一个,实际开发中,在MySQL数据库创建一张相应的请求方式+路径,以及请求时用户必须要有的权限是什么的数据表,通过初次查询缓存到redis中,之后就可以通过redis进行数据读取了,内存速度快。

  1. package com.white.gateway.config;
  2. import cn.hutool.core.collection.CollectionUtil;
  3. import cn.hutool.core.convert.Convert;
  4. import cn.hutool.core.util.StrUtil;
  5. import jdk.nashorn.internal.runtime.GlobalConstants;
  6. import lombok.AllArgsConstructor;
  7. import lombok.extern.slf4j.Slf4j;
  8. import org.springframework.beans.factory.annotation.Autowired;
  9. import org.springframework.data.redis.core.RedisTemplate;
  10. import org.springframework.data.redis.core.StringRedisTemplate;
  11. import org.springframework.http.HttpMethod;
  12. import org.springframework.http.server.reactive.ServerHttpRequest;
  13. import org.springframework.security.authorization.AuthorizationDecision;
  14. import org.springframework.security.authorization.ReactiveAuthorizationManager;
  15. import org.springframework.security.core.Authentication;
  16. import org.springframework.security.core.GrantedAuthority;
  17. import org.springframework.security.web.server.authorization.AuthorizationContext;
  18. import org.springframework.stereotype.Component;
  19. import org.springframework.util.AntPathMatcher;
  20. import org.springframework.util.PathMatcher;
  21. import reactor.core.publisher.Mono;
  22. import java.util.ArrayList;
  23. import java.util.List;
  24. import java.util.Map;
  25. /**
  26. * @ResourceServerManager.java的作用:鉴权管理器的相关配置
  27. * 负责被ResourceServerConfig.java文件引用
  28. * @author: white文
  29. * @time: 2023/5/30 0:57
  30. */
  31. @Component
  32. @AllArgsConstructor
  33. @Slf4j
  34. public class ResourceServerManager implements ReactiveAuthorizationManager<AuthorizationContext> {
  35. @Autowired
  36. private RedisTemplate redisTemplate;
  37. @Override
  38. public Mono<AuthorizationDecision> check(Mono<Authentication> mono, AuthorizationContext authorizationContext) {
  39. ServerHttpRequest request = authorizationContext.getExchange().getRequest();
  40. if (request.getMethod() == HttpMethod.OPTIONS) { // 预检请求放行
  41. return Mono.just(new AuthorizationDecision(true));
  42. }
  43. PathMatcher pathMatcher = new AntPathMatcher();
  44. String method = request.getMethodValue();
  45. String path = request.getURI().getPath();
  46. String restfulPath = method + ":" + path; // RESTFul接口权限设计: https://www.cnblogs.com/haoxianrui/p/14961707.html
  47. String token = request.getHeaders().getFirst("Authorization");
  48. // 如果token为空 或 不是以"bearer "为前缀 则无效并且需要鉴权
  49. if (!StrUtil.isNotBlank(token) || !StrUtil.startWithIgnoreCase(token, "Bearer ") ) {
  50. log.info("token为空 或 不是以 bearer 为前缀 则无效并且需要鉴权");
  51. return Mono.just(new AuthorizationDecision(false));
  52. }
  53. log.info("鉴权开始");
  54. /**
  55. * 鉴权开始
  56. *
  57. * 缓存取 [URL权限-角色集合] 规则数据
  58. * urlPermRolesRules = [{'key':'GET:/admin/*','value':['ADMIN','TEST']},...]
  59. */
  60. Map<String, Object> urlPermRolesRules = redisTemplate.opsForHash().entries("auth:resourceRolesMap");
  61. if (urlPermRolesRules.isEmpty()) {
  62. log.info("空的,我手动加一些上去");
  63. ArrayList<String> objects = new ArrayList<>();
  64. objects.add("TEST");
  65. objects.add("USER");
  66. redisTemplate.opsForHash().put("auth:resourceRolesMap","GET:/admin/*",objects);
  67. urlPermRolesRules = redisTemplate.opsForHash().entries("auth:resourceRolesMap");
  68. }
  69. // 根据请求路径获取有访问权限的角色列表
  70. List<String> authorizedRoles = new ArrayList<>(); // 拥有访问权限的角色
  71. boolean requireCheck = false; // 是否需要鉴权,默认未设置拦截规则不需鉴权
  72. for (Map.Entry<String, Object> permRoles : urlPermRolesRules.entrySet()) {
  73. String perm = permRoles.getKey();
  74. System.out.println("路径:"+perm+" 值:"+permRoles.getValue().toString());
  75. // 判断传过来的 方法:路径 是否在redis缓存中
  76. if (pathMatcher.match(perm, restfulPath)) {
  77. List<String> roles = Convert.toList(String.class, permRoles.getValue());
  78. // 加入授权数组中
  79. authorizedRoles.addAll(roles);
  80. if (requireCheck == false) {
  81. requireCheck = true;
  82. }
  83. }
  84. }
  85. // 没有设置拦截规则放行
  86. if (requireCheck == false) {
  87. return Mono.just(new AuthorizationDecision(true));
  88. }
  89. // 判断JWT中携带的用户角色是否有权限访问
  90. Mono<AuthorizationDecision> authorizationDecisionMono = mono
  91. .filter(Authentication::isAuthenticated)
  92. .flatMapIterable(Authentication::getAuthorities)
  93. .map(GrantedAuthority::getAuthority)
  94. .any(authority -> {
  95. String roleCode = StrUtil.removePrefix(authority,"ROLE_");// ROLE_ADMIN移除前缀ROLE_得到用户的角色编码ADMIN
  96. if (String.valueOf("ADMIN").equals(roleCode)) {
  97. return true; // 如果是超级管理员则放行
  98. }
  99. boolean hasAuthorized = CollectionUtil.isNotEmpty(authorizedRoles) && authorizedRoles.contains(roleCode);
  100. return hasAuthorized;
  101. })
  102. .map(AuthorizationDecision::new)
  103. .defaultIfEmpty(new AuthorizationDecision(false));
  104. return authorizationDecisionMono;
  105. }
  106. }

9.ResourceServerConfig

在该文件下,如果想实现 token无效或者已过期自定义响应(ServerAuthenticationEntryPoint 和 自定义未授权响应(ServerAccessDeniedHandler) 的话,可以自定义配置返回前端的相关配置,以下代码没做实现,采用程序默认返回给前端的401,如下效果:

  1. package com.white.gateway.config;
  2. import cn.hutool.core.convert.Convert;
  3. import cn.hutool.core.util.ArrayUtil;
  4. import com.white.gateway.filter.IgnoreUrlsRemoveJwtFilter;
  5. import lombok.Setter;
  6. import lombok.SneakyThrows;
  7. import lombok.extern.slf4j.Slf4j;
  8. import org.springframework.beans.factory.annotation.Autowired;
  9. import org.springframework.context.annotation.Bean;
  10. import org.springframework.context.annotation.Configuration;
  11. import org.springframework.core.convert.converter.Converter;
  12. import org.springframework.security.authentication.AbstractAuthenticationToken;
  13. import org.springframework.security.config.annotation.web.reactive.EnableWebFluxSecurity;
  14. import org.springframework.security.config.web.server.SecurityWebFiltersOrder;
  15. import org.springframework.security.config.web.server.ServerHttpSecurity;
  16. import org.springframework.security.oauth2.jwt.Jwt;
  17. import org.springframework.security.oauth2.server.resource.authentication.JwtAuthenticationConverter;
  18. import org.springframework.security.oauth2.server.resource.authentication.JwtGrantedAuthoritiesConverter;
  19. import org.springframework.security.oauth2.server.resource.authentication.ReactiveJwtAuthenticationConverterAdapter;
  20. import org.springframework.security.web.server.SecurityWebFilterChain;
  21. import reactor.core.publisher.Mono;
  22. import java.security.interfaces.RSAPublicKey;
  23. import java.util.List;
  24. /**
  25. * 资源服务器配置
  26. */
  27. @Configuration
  28. @EnableWebFluxSecurity
  29. @Slf4j
  30. public class ResourceServerConfig {
  31. @Autowired
  32. private ResourceServerManager resourceServerManager;
  33. @Autowired
  34. private IgnoreUrlsConfig ignoreUrlsConfig;
  35. @Autowired
  36. private IgnoreUrlsRemoveJwtFilter ignoreUrlsRemoveJwtFilter;
  37. @Bean
  38. public SecurityWebFilterChain securityWebFilterChain(ServerHttpSecurity http) {
  39. http
  40. .oauth2ResourceServer()
  41. .jwt()
  42. .jwtAuthenticationConverter(jwtAuthenticationConverter());
  43. //TODO 对白名单路径,直接移除JWT请求头
  44. http.addFilterBefore(ignoreUrlsRemoveJwtFilter, SecurityWebFiltersOrder.AUTHENTICATION);
  45. http.authorizeExchange()
  46. //白名单配置
  47. .pathMatchers(Convert.toStrArray(ignoreUrlsConfig.getUrls())).permitAll()
  48. //鉴权管理器配置
  49. .anyExchange().access(resourceServerManager)
  50. .and().csrf().disable();
  51. return http.build();
  52. }
  53. /**
  54. * @link https://blog.csdn.net/qq_24230139/article/details/105091273
  55. * ServerHttpSecurity没有将jwt中authorities的负载部分当做Authentication
  56. * 需要把jwt的Claim中的authorities加入
  57. * 方案:重新定义权限管理器,默认转换器JwtGrantedAuthoritiesConverter
  58. */
  59. @Bean
  60. public Converter<Jwt, ? extends Mono<? extends AbstractAuthenticationToken>> jwtAuthenticationConverter() {
  61. JwtGrantedAuthoritiesConverter jwtGrantedAuthoritiesConverter = new JwtGrantedAuthoritiesConverter();
  62. jwtGrantedAuthoritiesConverter.setAuthorityPrefix("ROLE_");
  63. jwtGrantedAuthoritiesConverter.setAuthoritiesClaimName("authorities");
  64. JwtAuthenticationConverter jwtAuthenticationConverter = new JwtAuthenticationConverter();
  65. jwtAuthenticationConverter.setJwtGrantedAuthoritiesConverter(jwtGrantedAuthoritiesConverter);
  66. return new ReactiveJwtAuthenticationConverterAdapter(jwtAuthenticationConverter);
  67. }
  68. }

10.RedisConfig

  1. package com.white.gateway.config;
  2. import com.fasterxml.jackson.annotation.JsonAutoDetect;
  3. import com.fasterxml.jackson.annotation.PropertyAccessor;
  4. import com.fasterxml.jackson.databind.ObjectMapper;
  5. import org.springframework.cache.annotation.CachingConfigurerSupport;
  6. import org.springframework.cache.annotation.EnableCaching;
  7. import org.springframework.context.annotation.Bean;
  8. import org.springframework.context.annotation.Configuration;
  9. import org.springframework.data.redis.connection.RedisConnectionFactory;
  10. import org.springframework.data.redis.core.RedisTemplate;
  11. import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
  12. import org.springframework.data.redis.serializer.StringRedisSerializer;
  13. import javax.annotation.Resource;
  14. /*
  15. * Redis配置
  16. * 解决redis在业务逻辑处理层RedisCon上不出错,缓存序列化问题
  17. * @author: white
  18. * */
  19. @Configuration
  20. @EnableCaching
  21. public class RedisConfig extends CachingConfigurerSupport {
  22. @Resource
  23. RedisConnectionFactory redisConnectionFactory;
  24. @Bean
  25. public RedisTemplate<String,Object> redisTemplate(){
  26. System.out.println("gateway 读取redis配置");
  27. RedisTemplate<String,Object> redisTemplate=new RedisTemplate<>();
  28. redisTemplate.setConnectionFactory(redisConnectionFactory);
  29. //Json序列化配置
  30. //1、String的序列化
  31. StringRedisSerializer stringRedisSerializer=new StringRedisSerializer();
  32. // key采用String的序列化方式
  33. redisTemplate.setKeySerializer(stringRedisSerializer);
  34. // hash的key也采用String的序列化方式
  35. redisTemplate.setHashKeySerializer(stringRedisSerializer);
  36. //2、json解析任意的对象(Object),变成json序列化
  37. Jackson2JsonRedisSerializer<Object> serializer=new Jackson2JsonRedisSerializer<Object>(Object.class);
  38. ObjectMapper mapper=new ObjectMapper(); //用ObjectMapper进行转义
  39. mapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
  40. //该方法是指定序列化输入的类型,就是将数据库里的数据按照一定类型存储到redis缓存中。
  41. mapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
  42. serializer.setObjectMapper(mapper);
  43. // value序列化方式采用jackson
  44. redisTemplate.setValueSerializer(serializer);
  45. // hash的value序列化方式采用jackson
  46. redisTemplate.setHashValueSerializer(serializer);
  47. return redisTemplate;
  48. }
  49. }

11、TokenVar

  1. package var;
  2. public interface TokenVar {
  3. public static final String APP_SECRET ="white";
  4. public static final String TOKEN_HEAD="Authorization"; // 认证信息Http请求头
  5. public static final String TOKEN_PREFIX = "Bearer "; // JWT令牌前缀
  6. /**
  7. * JWT存储权限前缀
  8. */
  9. String AUTHORITY_PREFIX = "ROLE_";
  10. /**
  11. * JWT存储权限属性
  12. */
  13. String AUTHORITY_CLAIM_NAME = "authorities";
  14. /**
  15. * 后台client_id
  16. */
  17. String ADMIN_CLIENT_ID = "api-admin";
  18. /**
  19. * 前端client_id
  20. */
  21. String PORTAL_CLIENT_ID = "api-portal";
  22. /**
  23. * 后台接口路径匹配
  24. */
  25. String ADMIN_URL_PATTERN = "/admin/**";
  26. /**
  27. * Redis缓存权限规则key
  28. */
  29. String RESOURCE_ROLES_MAP_KEY = "auth:resourceRolesMap";
  30. /**
  31. * 用户信息Http请求头
  32. */
  33. String USER_TOKEN_HEADER = "user";
  34. /**
  35. * 黑名单
  36. */
  37. String TOKEN_BLACKLIST_PREFIX = "blacklist";
  38. }

 三、测试

与第二篇文章的测试相同,只不过我们将地址的端口改成10000,意思是通过网关去请求oauth认证授权。

1、请求授权码

http://localhost:10000/uaa/oauth/authorize?client_id=123&response_type=code&scop=all&redirect_uri=http://localhost:10000

自动跳转到:http://localhost:10000/uaa/login

2、请求令牌

3、验证令牌

4、刷新令牌

 5.请求资源,不带token

在前面的过滤中,我们仅仅对/user/**,/uaa/**两个路径进行白名单路径设置,而在user-service模块中,小编还设置一个/admin/**的一个路径,该路径没有被设置进白名单,并且在redis的设置中,该路径需要权限为:admin

现在不带token来请求/admin/1,如下,结果为401:

 6.请求资源,带有token

现在我们带着token,并且token中的用户信息权限为admin

四、进一步调优

到此,gateway+oauth整合完成了,接下来会在评论区出下一章,下一章会针对oauth的推出登录如何解决以及如何整合第三方应用进行登录(如:gitee平台)。

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

闽ICP备14008679号