微服务集成springsecurity实现认证
module:auth
1.添加依赖:spring-cloud-starter-security与spring-cloud-starter-oauth2
2.配置WebSecurityConfig:注入AuthenticationManager覆写configure
3.配置tokenConfig
4.授权服务器配置:AuthorizationServer extends AuthorizationServerConfigurerAdapter配置客户端详细任务,令牌端点配置
5.实现UserDetailsService,覆写loadUserByUsername(最熟悉的一集)
tips:这里return 的UserDetails对象不用自己创建,springsecurity提供了一个User类实现了UserDetails,通过建造者模式可以直接生成username,password,authorities等信息。这里如果需要多参数分发给其他module使用,建议的做法是将数据库中查出来的对象通过json转成字符串存入username,后续可以直接将username反写成具体的class
module:gateway
首先明确网关的作用:路由转发、认证、白名单放行:针对当前网关的路由进行转发,如果是白名单则直接放行,如果是需要JWT校验则需要校验JWT合法性
security中提供了认证与授权,这里我们在网关进行了认证,也就是说授权模块是在各个微服务中进行的
gateway集成springsecurity:
1.添加依赖:spring-cloud-starter-security与spring-cloud-starter-oauth2
2.添加配置:过滤器;再添加tokenConfig、securityConfig
/**
*
* @description 网关认证过滤器:这段代码主要是作为过滤器去处理一个http请求,首先是检查请求路径是否在白名单中,请求是否携带token/有没有过期等安全相关检查
*/
@Component
@Slf4j
public class GatewayAuthFilter implements GlobalFilter, Ordered { //白名单
private static List<String> whitelist = null; static {
//加载白名单
try (
InputStream resourceAsStream = GatewayAuthFilter.class.getResourceAsStream("/security-whitelist.properties");
) {
Properties properties = new Properties();
properties.load(resourceAsStream);
Set<String> strings = properties.stringPropertyNames();
whitelist= new ArrayList<>(strings); } catch (Exception e) {
log.error("加载/security-whitelist.properties出错:{}",e.getMessage());
e.printStackTrace();
}
} @Autowired
private TokenStore tokenStore; @Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
String requestUrl = exchange.getRequest().getPath().value();
AntPathMatcher pathMatcher = new AntPathMatcher();
//白名单放行
for (String url : whitelist) {
if (pathMatcher.match(url, requestUrl)) {
return chain.filter(exchange);
}
} //检查token是否存在
String token = getToken(exchange);
if (StringUtils.isBlank(token)) {
return buildReturnMono("没有认证",exchange);
}
//判断是否是有效的token
OAuth2AccessToken oAuth2AccessToken;
try {
oAuth2AccessToken = tokenStore.readAccessToken(token); boolean expired = oAuth2AccessToken.isExpired();
if (expired) {
return buildReturnMono("认证令牌已过期",exchange);
}
return chain.filter(exchange);
} catch (InvalidTokenException e) {
log.info("认证令牌无效: {}", token);
return buildReturnMono("认证令牌无效",exchange);
} } /**
* 获取token
*/
private String getToken(ServerWebExchange exchange) {
String tokenStr = exchange.getRequest().getHeaders().getFirst("Authorization");
if (StringUtils.isBlank(tokenStr)) {
return null;
}
String token = tokenStr.split(" ")[1];
if (StringUtils.isBlank(token)) {
return null;
}
return token;
}
private Mono<Void> buildReturnMono(String error, ServerWebExchange exchange) {
ServerHttpResponse response = exchange.getResponse();
String jsonString = JSON.toJSONString(new RestErrorResponse(error));
byte[] bits = jsonString.getBytes(StandardCharsets.UTF_8);
DataBuffer buffer = response.bufferFactory().wrap(bits);
response.setStatusCode(HttpStatus.UNAUTHORIZED);
response.getHeaders().add("Content-Type", "application/json;charset=UTF-8");
return response.writeWith(Mono.just(buffer));
} @Override
public int getOrder() {
return 0;
}
}
// 假设已经从请求中获得了token
String token = getToken(exchange); // 如果token存在且不为空
if (token != null && !token.isEmpty()) {
// 创建一个新的ServerHttpRequest,并添加token到Authorization头
ServerHttpRequest mutatedRequest = exchange.getRequest().mutate()
.header("Authorization", "Bearer " + token)
.build(); // 使用ServerWebExchangeDecorator来包装原始的ServerWebExchange,并且使用修改后的请求
ServerWebExchange mutatedExchange = exchange.mutate()
.request(mutatedRequest)
.build(); return chain.filter(mutatedExchange);
}
3.配置白名单security-whitelist.properties
/media/open/**=媒资管理公开访问接口
4.在其他微服务模块中放行所有路由,并且直接通过SecurityContextHolder.getContext().getAuthentication()获取对象(因为在网关中已经校验完了,这里只负责授权)
module:others
1.包装一个SecurityUtil。SecurityContextHolder.getContext().getAuthentication().getPrincipal();即可获得具体username,然后将username转为实体类即可使用
@Slf4j
public class SecurityUtil { public static XcUser getUser() {
try {
Object principalObj = SecurityContextHolder.getContext().getAuthentication().getPrincipal();
if (principalObj instanceof String) {
//取出用户身份信息
String principal = principalObj.toString();
//将json转成对象
XcUser user = JSON.parseObject(principal, XcUser.class);
return user;
}
} catch (Exception e) {
log.error("获取当前登录用户身份出错:{}", e.getMessage());
e.printStackTrace();
} return null;
} @Data
public static class XcUser implements Serializable { private static final long serialVersionUID = 1L; private String id; private String username; private String password; private String salt; private String name;
private String nickname;
private String wxUnionid;
private String companyId;
/**
* 头像
*/
private String userpic; private String utype; private LocalDateTime birthday; private String sex; private String email; private String cellphone; private String qq; /**
* 用户状态
*/
private String status; private LocalDateTime createTime; private LocalDateTime updateTime; } }
使用说明:上文使用了成员内部类,XcUser定义在外部类的成员位置,其不能创建独立对象,必须依靠外部类实例.new 内部类()来创建实例
SecurityUtil.XcUser user = SecurityUtil.getUser();
Q&A:
token在gateway中传递下去的?
(无oauth2集成)一般情况下我们需要修改ServerWebExchange里的ServerHttpRequest,但是ServerHttpRequest是不可变的。因此如果我们需要添加上token,就需要新建一个ServerWebExchange,重写ServerHttpRequest。
除此以外,因为我们还会将请求传递给下一个GatewayFilterChain,我们可以在这个请求传递的时候通过修改ServerWebExchange的MutableHttpRequest:
(有oauth2集成)springsecurity的过滤器链会自动处理从请求中提取token,并将其附加到上下文中,下游的过滤器会通过springsecurity的API获取他
为什么其他微服务模块能直接通过SecurityContextHolder.getContext().getAuthentication()获取对象?
在微服务中,每一个模块都有独属于自己的JVM,拥有独属于自己的线程,也就是说每个模块的SecurityContext是不一样的。当我们使用oauth2,用户通过上述gateway进行认证,并获取一个jwt将其放在request中。
当一个模块接收到一个包含oauth2令牌的http请求时,他会使用这个令牌来验证用户身份,并且基于令牌构建一个新的SecurityContext。也就是说SecurityContext的实现其实是局限于单个服务的单个线程的,跨服务的安全信息传递是由oauth2进行的
微服务集成springsecurity实现认证的更多相关文章
- ScalaPB(0): 找寻合适的内部系统微服务集成工具
前一段时间我们探讨了SDP的一个基于集群的综合数据平台解决方案,由多种数据库组成,包括:JDBC, Cassandra 及MongoDB.其中Cassandra和MongoDB属于分布式数据库,可以在 ...
- (12)go-micro微服务JWT跨域认证
目录 一 JWT介绍 二 JWT优缺点 三 JWT使用 1. 导包和数据定义 2.生成JWT 3.解析JWT 4.完整代码 四 最后 一 JWT介绍 JWT 英文名是 Json Web Token , ...
- Spring Cloud(一)简单的微服务集成Eureka
1 Spring Cloud简介 1.1 简介 Spring Cloud项目的官方网址:https://projects.spring.io/spring-clo ...
- Spring cloud微服务安全实战-6-2JWT认证之认证服务改造
首先来解决认证的问题. 1.效率低,每次认证都要去认证服务器调一次服务. 2.传递用户身份,在请求头里面, 3.服务之间传递请求头比较麻烦. jwt令牌. spring提供了工具,帮你在微服务之间传递 ...
- 微服务系列之授权认证(一) OAuth 2.0 和 OpenID Connect
1.传统架构的授权认证 传统应用架构,用户使用账号密码登录后,可以使用前端cookie存储登录状态,也可以使用后端session方式存储登录状态,小应用这么做其实很高效实用,当应用需要横向扩展时,就需 ...
- 微服务系列之授权认证(三) JWT
1.JWT简介 官方定义:JWT是JSON Web Token的缩写,JSON Web Token是一个开放标准(RFC 7519),它定义了一种紧凑的.自包含的方式,可以将各方之间的信息作为JSON ...
- Spring Cloud微服务集成配置中心
1. 搭建Spring Cloud Config配置中心(见上一篇博客) 2. 创建微服务项目bounter-simon-app,pom文件如下: <?xml version="1.0 ...
- 微服务系列之授权认证(二) identity server 4
1.简介 IdentityServer4 是为ASP.NET Core系列量身打造的一款基于 OpenID Connect 和 OAuth 2.0 认证授权框架. 官方文档:https://ident ...
- Devops 开发运维高级篇之Jenkins+Docker+SpringCloud微服务持续集成(上)
Devops 开发运维高级篇之Jenkins+Docker+SpringCloud微服务持续集成(上) Jenkins+Docker+SpringCloud持续集成流程说明 大致流程说明: 1) 开发 ...
- Taurus.MVC 微服务框架 入门开发教程:项目集成:1、服务端:注册中心、网关(提供可运行程序下载)。
系列目录: 本系列分为项目集成.项目部署.架构演进三个方向,后续会根据情况调整文章目录. 本系列第一篇:Taurus.MVC V3.0.3 微服务开源框架发布:让.NET 架构在大并发的演进过程更简单 ...
随机推荐
- Android OpenMAX(四)OMX Core
假设我们已经写好了所有的OMX组件,有vdec.venc.adec.aenc,接下来问题来了,我们应该如何管理这些组件呢(创建.销毁)?这一篇文章我们向上一层学习OMX Core提供的标准API. O ...
- Flutter(一):MAC的Flutter安装指南
官网地址 官网: https://flutter.dev Github: https://github.com/flutter/flutter Git的核心分支包括master.dev.stable. ...
- SpringBoot使用@Value获取不到值的问题
背景 在一次SpringBoot项目改造为Cloud的过程中,使用Nacos作为配置中心获取属性,改造后程序启动报错,查看日志,定位到代码: 解决方案 如果了解Bean的生命周期的同学应该知道,Spr ...
- 开源一站式敏捷测试管理,极简项目管理平台 itest(爱测试) 6.6.2 发布,便捷迫切功能增强
(一)itest 简介及更新说明 itest 开源敏捷测试管理,testOps 践行者,极简的任务管理,测试管理,缺陷管理,测试环境管理,接口测试5合1,又有丰富的统计分析.可按测试包分配测试用例执行 ...
- 引用(包含) import wxss样式
引用(包含) 把模板定义到外部,然后多个页面间可以共用使用定义的模板WXML结构显示. https://developers.weixin.qq.com/miniprogram/dev/referen ...
- .NET5 ASP.NET Core 使用 EF Core MS SQL SERVER DB First
.NET5 ASP.NET Core 使用 EF Core MS SQL SERVER DB First 开发工具:VS2019 1.修改appsettings.json,增加一项. "Co ...
- 你唯一需要的是“Wide Events”,而非“Metrics、Logs、Traces”
Charity Majors 的这句话可能是对科技行业当前可观察性状态的最好总结--完全的.大规模的混乱.大家都很困惑.什么是 trace?什么是 span?一行日志就是一个 span 吗?如果我有日 ...
- 燕千云 YQCloud 数智化业务服务平台 发布1.12版本
2022年4月29日,燕千云 YQCloud 数智化业务服务平台发布1.12版本,优化客户服务场景.深化智能预测服务的应用,加强系统在多渠道方面的集成,全面提升企业数智化服务的能力! 作为企业数字化服 ...
- #PowerBi 1分钟学会,用PowerBi获取数据库最近90天的数据(DATE_SUB)
在powerbi报表中,我们往往会对数据源进行日常刷新,powerbi链接了数据库的情况下,根据日期灵活取数是我们必须掌握的一个技能. 在本文中,我们将介绍如何使用 SQL 的 DATE_SUB 函数 ...
- 随机二次元图片API第三弹
Tips:当你看到这个提示的时候,说明当前的文章是由原emlog博客系统搬迁至此的,文章发布时间已过于久远,编排和内容不一定完整,还请谅解` 随机二次元图片API第三弹 日期:2020-3-10 阿珏 ...