父模块

pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><groupId>groupId</groupId><artifactId>sc-scaffold</artifactId><version>0.1</version><modules><module>config-center</module><module>gateway-center</module><module>user-center</module></modules><name>${project.artifactId}</name><packaging>pom</packaging><properties><spring-boot.version>2.4.0</spring-boot.version><spring-cloud.version>2020.0.0</spring-cloud.version><spring-cloud-alibaba.version>2020.0.RC1</spring-cloud-alibaba.version><project.build.sourceEncoding>UTF-8</project.build.sourceEncoding><maven.compiler.source>1.8</maven.compiler.source><maven.compiler.target>1.8</maven.compiler.target><fastjson.version>1.2.75</fastjson.version></properties><profiles><profile><id>dev</id><properties><!-- 环境标识,需要与配置文件的名称相对应 --><profiles.active>dev</profiles.active></properties><activation><!-- 默认环境 --><activeByDefault>true</activeByDefault></activation></profile></profiles><dependencies><!--bootstrap 启动器--><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-bootstrap</artifactId></dependency><!--配置文件处理器--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-configuration-processor</artifactId></dependency><!--监控--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-actuator</artifactId></dependency><!--日志--><dependency><groupId>ch.qos.logback</groupId><artifactId>logback-core</artifactId></dependency><!--Lombok--><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId></dependency><!--测试依赖--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency><!--JSON--><dependency><groupId>com.alibaba</groupId><artifactId>fastjson</artifactId><version>${fastjson.version}</version></dependency></dependencies><dependencyManagement><dependencies><!-- spring boot 依赖 --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-dependencies</artifactId><version>${spring-boot.version}</version><type>pom</type><scope>import</scope></dependency><!-- spring cloud 依赖 --><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-dependencies</artifactId><version>${spring-cloud.version}</version><type>pom</type><scope>import</scope></dependency><!-- spring cloud alibaba 依赖 --><dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-alibaba-dependencies</artifactId><version>${spring-cloud-alibaba.version}</version><type>pom</type><scope>import</scope></dependency><!--数据库--><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>8.0.20</version></dependency><dependency><groupId>com.alibaba</groupId><artifactId>druid</artifactId><version>1.2.0</version></dependency><dependency><groupId>org.mybatis.spring.boot</groupId><artifactId>mybatis-spring-boot-starter</artifactId><version>2.1.4</version></dependency></dependencies></dependencyManagement><build><!--指定filtering=true.maven的占位符解析表达式就可以用于它里面的文件--><resources><resource><directory>src/main/resources</directory><filtering>true</filtering></resource></resources><plugins><!--支持yaml读取pom的参数--><plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-resources-plugin</artifactId><version>3.2.0</version><configuration><encoding>UTF-8</encoding><delimiters><delimiter>@</delimiter></delimiters><useDefaultDelimiters>false</useDefaultDelimiters></configuration></plugin></plugins></build>
</project>

User用户中心

两个controller用来测试,一个放行,一个需要Token认证。

AuthController

@RestController
@RequestMapping(path = "/auth")
public class AuthController {@GetMapping(path = "/c")public String c() {return "user center ok c";}@GetMapping(path = "/d")public String d() {return "user center ok d";}
}

UserController

/*** @author zhe.xiao* @date 2021-03-23 17:18* @description*/
@Slf4j
@RestController
@RequestMapping(path = "/user")
public class UserController {@GetMapping(path = "/a")public String a() {return "user center ok a";}@GetMapping(path = "/b")public String b() {return "user center ok b";}
}

Gateway网关

pom

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"><parent><artifactId>sc-scaffold</artifactId><groupId>groupId</groupId><version>0.1</version></parent><modelVersion>4.0.0</modelVersion><artifactId>gateway-center</artifactId><packaging>jar</packaging><dependencies><!--gateway ===  内置webflux作为web服务器--><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-gateway</artifactId></dependency><!--监控信息--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-actuator</artifactId></dependency><!--注册中心--><dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId></dependency><!-- loadbalancer --><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-loadbalancer</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-security</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-redis</artifactId></dependency></dependencies><build><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId></plugin></plugins></build>
</project>

application.yml

server:port: 2000tomcat:uri-encoding: UTF-8spring:application:name: @artifactId@redis:host: redis-hostport: 6379cloud:nacos:discovery:server-addr: nacos-host:8848gateway:globalcors:cors-configurations:'[/**]':allowedOrigins: "*"allowedMethods: "*"allowedHeaders: "*"discovery:locator:enabled: true #使用服务发现路由routes:- id: config-routeruri: lb://config-center #服务注册名predicates:- Path=/api-config/** #路径匹配规则filters:- StripPrefix=1 #匹配第一个api-*后,在转发路由的时候会去除api-*- id: user-routeruri: lb://user-centerpredicates:- Path=/api-user/**filters:- StripPrefix=1

核心的配置安全策略

介绍

Spring Cloud Gateway中使用的是Spring-Webflux,所以不能用Spring MVC的那套安全配置。

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

webflux mvc 作用
@EnableWebFluxSecurity @EnableWebSecurity 开启security配置
ServerAuthenticationSuccessHandler AuthenticationSuccessHandler 登录成功Handler
ServerAuthenticationFailureHandler AuthenticationFailureHandler 登陆失败Handler
ReactiveAuthorizationManager AuthorizationManager 认证管理
ServerSecurityContextRepository SecurityContextHolder 认证信息存储管理
ReactiveUserDetailsService UserDetailsService 用户登录
ReactiveAuthorizationManager AccessDecisionManager 鉴权管理
ServerAuthenticationEntryPoint AuthenticationEntryPoint 未认证Handler
ServerAccessDeniedHandler AccessDeniedHandler 鉴权失败Handler

ScAccessDeniedHandler

/*** 权限认证失败执行** @author zhe.xiao* @date 2021-04-12 17:33* @description*/
@Slf4j
@Component
public class ScAccessDeniedHandler implements ServerAccessDeniedHandler {@Overridepublic Mono<Void> handle(ServerWebExchange exchange, AccessDeniedException denied) {ServerHttpResponse response = exchange.getResponse();response.setStatusCode(HttpStatus.FORBIDDEN);response.getHeaders().add("Content-Type", "application/json; charset=UTF-8");HashMap<String, String> map = new HashMap<>();map.put("code", "000000");map.put("message", "未授权禁止访问");log.error("access forbidden path={}", exchange.getRequest().getPath());DataBuffer dataBuffer = response.bufferFactory().wrap(JSON.toJSONBytes(map));return response.writeWith(Mono.just(dataBuffer));}
}

ScAuthenticationEntryPoint

/*** 认证失败执行* @author zhe.xiao* @date 2021-04-15 11:54* @description*/
@Slf4j
@Component
public class ScAuthenticationEntryPoint implements ServerAuthenticationEntryPoint {@Overridepublic Mono<Void> commence(ServerWebExchange exchange, AuthenticationException ex) {ServerHttpResponse response = exchange.getResponse();response.setStatusCode(HttpStatus.FORBIDDEN);response.getHeaders().add("Content-Type", "application/json; charset=UTF-8");HashMap<String, String> map = new HashMap<>();map.put("code", "000000");map.put("message", "未授权禁止访问");log.error("access forbidden path={}", exchange.getRequest().getPath());DataBuffer dataBuffer = response.bufferFactory().wrap(JSON.toJSONBytes(map));return response.writeWith(Mono.just(dataBuffer));}
}

ScSecurityContextRepository

/*** 1. 把header拿到的token放入AuthenticationToken** @author zhe.xiao* @date 2021-04-14 23:32* @description*/
@Slf4j
@Component
public class ScSecurityContextRepository implements ServerSecurityContextRepository {@AutowiredScAuthenticationManager scAuthenticationManager;@Overridepublic Mono<Void> save(ServerWebExchange exchange, SecurityContext context) {return Mono.empty();}@Overridepublic Mono<SecurityContext> load(ServerWebExchange exchange) {ServerHttpRequest request = exchange.getRequest();String authorization = request.getHeaders().getFirst("Authorization");log.info("ScSecurityContextRepository authorization = {}", authorization);return scAuthenticationManager.authenticate(new UsernamePasswordAuthenticationToken(authorization, null)).map(SecurityContextImpl::new);}
}

ScAuthenticationManager

/*** 2. 从AuthenticationToken读取Token并做用户数据解析** @author zhe.xiao* @date 2021-04-14 23:35* @description*/
@Slf4j
@Component
public class ScAuthenticationManager implements ReactiveAuthenticationManager {@Overridepublic Mono<Authentication> authenticate(Authentication authentication) {String tokenString = (String) authentication.getPrincipal();//校验tokenScUser scUser = parseToken(tokenString);log.info("ScAuthenticationManager scUser = {}", scUser);return Mono.just(authentication).map(auth -> {return new UsernamePasswordAuthenticationToken(scUser, null, null);});}/*** 校验token** @param tokenString* @return*/private ScUser parseToken(String tokenString) {//读取tokenString jwtToken = getJwtToken(tokenString);log.info("ScAuthenticationManager jwtToken = {}", jwtToken);//模拟认证成功if (StringUtils.hasText(jwtToken) && jwtToken.startsWith("a")) {return new ScUser().setId(1L).setName("zhexiao");}return null;}/*** 读取Jwt Token** @param authorization* @return*/private String getJwtToken(String authorization) {if (!StringUtils.hasText(authorization)) {return null;}boolean valid = authorization.startsWith("Bearer ");if (!valid) {return null;}return authorization.replace("Bearer ", "");}
}

ScAuthorizationManager

/*** 3. 权限验证,是否放行** @author zhe.xiao* @date 2021-04-15 11:12* @description*/
@Slf4j
@Component
public class ScAuthorizationManager implements ReactiveAuthorizationManager<AuthorizationContext> {@Overridepublic Mono<AuthorizationDecision> check(Mono<Authentication> authentication, AuthorizationContext authorizationContext) {return authentication.map(auth -> {ScUser scUser = (ScUser) auth.getPrincipal();log.info("ScAuthorizationManager scUser = {}", scUser);if (Objects.isNull(scUser)) {return new AuthorizationDecision(false);}return new AuthorizationDecision(true);}).defaultIfEmpty(new AuthorizationDecision(false));}
}

ScFilter

/*** 4. 请求通过后的额外操作处理** @author zhe.xiao* @date 2021-04-13 15:01* @description*/
@Slf4j
public class ScFilter implements WebFilter {@Overridepublic Mono<Void> filter(ServerWebExchange exchange, WebFilterChain chain) {log.info("UserFilter doing.... path={}", exchange.getRequest().getPath());Authentication authentication = SecurityContextHolder.getContext().getAuthentication();if (!Objects.isNull(authentication)) {Object principal = authentication.getPrincipal();log.info("UserFilter doing principal={}", principal);}return chain.filter(exchange);}
}

WebSecurityConfig 核心配置

/*** @author zhe.xiao* @date 2021-04-12 17:02* @description*/
@Configuration
@EnableWebFluxSecurity
public class WebSecurityConfig {@AutowiredPasswordEncoder passwordEncoder;@AutowiredScSecurityContextRepository scSecurityContextRepository;@AutowiredScAuthenticationManager scAuthenticationManager;@AutowiredScAuthorizationManager scAuthorizationManager;@AutowiredScAccessDeniedHandler scAccessDeniedHandler;@AutowiredScAuthenticationEntryPoint scAuthenticationEntryPoint;/*** 访问权限授权** @param http* @return*/@Beanpublic SecurityWebFilterChain springSecurityFilterChain(ServerHttpSecurity http) {http.csrf().disable().securityContextRepository(scSecurityContextRepository) //存储认证信息.authenticationManager(scAuthenticationManager) //认证管理.authorizeExchange(exchange -> exchange // 请求拦截处理.pathMatchers("/favicon.ico", "/api-user/user/**").permitAll().pathMatchers(HttpMethod.OPTIONS).permitAll().anyExchange().access(scAuthorizationManager) //权限).addFilterAfter(new ScFilter(), SecurityWebFiltersOrder.AUTHORIZATION) //拦截处理.exceptionHandling().accessDeniedHandler(scAccessDeniedHandler) //权限认证失败.and().exceptionHandling().authenticationEntryPoint(scAuthenticationEntryPoint); //认证失败return http.build();}
}

测试

  1. /api-user/user/a和/api-user/user/b 直接放行。

  1. /api-user/auth/c未加token,不放行

  1. /api-user/auth/d 加token,放行。(注意我的认证是模拟token字符串以a开头就属于合法)

不以a开头则认为是不合法的token。

SpringCloud Gateway + Spring Security相关推荐

  1. refreshtoken用mysql_「SpringCloud」 Spring Security OAuth2 Mysql管理在线Token

    原标题:「SpringCloud」 Spring Security OAuth2 Mysql管理在线Token 前言:Spring Cloud 分布式中的登录如何可视化的管理目前下发的令牌.使用情况. ...

  2. 【Spring Cloud Alibaba 实战 | 总结篇】Spring Cloud Gateway + Spring Security OAuth2 + JWT 实现微服务统一认证授权和鉴权

    一. 前言 hi,大家好~ 好久没更文了,期间主要致力于项目的功能升级和问题修复中,经过一年时间这里只贴出关键部分代码的打磨,[有来]终于迎来v2.0版本,相较于v1.x版本主要完善了OAuth2认证 ...

  3. SpringCloud整合spring security+ oauth2+Redis实现认证授权

    文章目录 设置通用父工程依赖 构建eureka注册中心 构建认证授权服务 配置文件设置 Security配置类 授权服务配置类 登录实现 测试验证 设置通用父工程依赖 在微服务构建中,我们一般用一个父 ...

  4. SpringCloud Gateway 通过redis实现限流【SpringCloud系列8】

    SpringCloud 大型系列课程正在制作中,欢迎大家关注与提意见. 程序员每天的CV 与 板砖,也要知其所以然,本系列课程可以帮助初学者学习 SpringBooot 项目开发 与 SpringCl ...

  5. 【SpringCloud】04 网关springcloud gateway

    网关springcloud gateway 上面的架构,会存在着诸多的问题: 客户端多次请求不同的微服务,增加客户端代码或配置编写的复杂性 认证复杂,每个服务都需要独立认证. 存在跨域请求,在一定场景 ...

  6. springcloud gateway ribbon使用_Github点赞接近 70k 的Spring Cloud学习教程+实战项目推荐!牛批!...

    这篇文章继续来推荐 Spring Cloud 的教程和实战项目了!想必不用不多说,大家都知道 Spring Cloud 的重要程度.几乎稍微有点规模的公司,一般都离不开要和微服务打交道.同时,Spri ...

  7. Gateway 整合 Spring Security鉴权

    目录 Spring-Security Spring-Webflux 注意 编码 项目环境版本 gradle 依赖 Spring-Security配置 1. Security核心配置 2.用户认证 3. ...

  8. 【Spring Cloud Spring Security Oauth2】Spring Security Oauth2 + Redis + Gateway网关 + Mybatis + Mysql 整合

    目录 一.环境要求 二.源码下载地址 三.参考文献 四.项目预览截图说明 五.oauth2.0认证授权项目 5.1 POM依赖 5.2 yml配置及启动类 5.3 认证配置与资源配置 5.4 自定义U ...

  9. nacos oaut服务地址_用户认证的例子:Spring Security oAuth2 + Spring Cloud Gateway + Nacos + Dubbo...

    这个例子是商城后台项目的一部分,主要使用了oAuth2的密码模式完成用户名密码认证功能.主要流程是:使用Nacos作为注册中心,操作用户的服务user-mgr-service作为服务提供者,注册到Na ...

最新文章

  1. Java学习必不可少的网站,快收藏起来
  2. 几种Linux包管理系统的命令对照
  3. C#复制图片_并重命名
  4. dbda.class.php 下载,DBDA
  5. Docker入坑指南之RUN
  6. Android开发之开发工具之Android Studio出现全屏的解决办法
  7. 完全编译安装boost
  8. python选定区域设置边框_Python教程:巧用openpyxl为指定区域设置边框为粗匣框线...
  9. eclipse easy shell plugin
  10. How to Leak a Context: Handlers Inner Classes
  11. SpringBoot2.1.5(11)---目录文件结构讲解
  12. 语句--分支语句if case
  13. jquery之父john resig见面会及jquery最新动态
  14. JAVA毕设项目宠物店管理系统设计与实现(Vue+Mybatis+Maven+Mysql+sprnig+SpringMVC)
  15. 《工业设计史》 第二章:手工艺设计阶段
  16. 机器学习高频面试题(41道)
  17. python投资组合有效边界,软核科普系列:用python帮你建立自己的投资组合
  18. 顾连康复中心一个月费用?医保能报销吗
  19. 解决微信小程序银行卡号输入转换格式
  20. 学生个人网页设计作品 HTML+CSS+JavaScript仿小米商城(8页) 学生个人网页模板 简单个人主页成品 个人网页制作 HTML学生个人网站作业设计代做

热门文章

  1. python量化:如何利用时间序列索引找到股票日线行情中的每个月的第一个交易日?每年的最后一个交易日?
  2. 数据处理分析模块 Pandas(3)
  3. pyspark- ml-features
  4. python输出一个函数多项式_python实现PolynomialFeatures多项式的方法
  5. 248Echarts - 3D 曲面(Parametric Surface Rose)
  6. SEO从业者打造个人品牌的八个建议
  7. 我今年,二十四五岁 (2018年深有体会)
  8. 秋日露营好去处,安化云台山星空露营公园
  9. 移动安全学习笔记——组件安全之组件暴露导致的安全问题(含实验)
  10. 标普500市值门槛提高今日生效 第一太阳能(First Solar)出局