Spring Cloud微服务安全实战_6-3_jwt认证之网关和服务改造

摘要:
之前之所以手写是为了理解SpringSecurity-OAuth内部的实现。在网关的配置文件里配置:资源服务器启动的时候,就会去认证服务器拿这个key,所以启动网关前必须要保证认证服务器是启动的。此时,各个微服务也需要解析jwt,获取用户信息。再次重启认证服务器,重启网关,正常启动。其实SpringSecurity-OAuth已经替你把这些事情做好了。下面改造订单微服务和价格微服务,在他们之间传递用户信息。

上一节在认证服务器里,将token 由uuid改造成了JWT,之前在网关上拿到令牌access_token后,需要去认证服务器校验令牌,将令牌信息转换为用户信息。

现在有了jwt后,由于jwt是自包含的,已经包含了用户的身份信息,所以在网关上不需要去认证服务器验令牌了。

Spring Cloud微服务安全实战_6-3_jwt认证之网关和服务改造第1张

之前在网关上所做的这些去认证服务器验令牌信息,转换为用户信息,去认证服务器做权限的判断,这些其实SpringSecurity-OAuth都已经实现好了的。之前之所以手写是为了理解SpringSecurity-OAuth内部的实现。

1,删掉网关上filter包里的过滤器

Spring Cloud微服务安全实战_6-3_jwt认证之网关和服务改造第2张

2,在网关项目里加上依赖
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-oauth2</artifactId>
</dependency>
3,配置获取jwt验签的key的uri
认证服务器生成Jwt的时候,是进行了签名的,有一个签名的key;解析Jwt,需要验签,也需要这个key值,所以需要告诉网关,去哪里获取这个签名的key。
在网关的配置文件里配置: (这个uri具体在org.springframework.security.oauth2.provider.endpoint.TokenKeyEndpoint里处理)
资源服务器启动的时候,就会去认证服务器拿这个key,所以启动网关前必须要保证认证服务器是启动的。
security:
oauth2:
resource:
jwt:
key-uri: http://auth.nb.com:9090/oauth/token_key #获取解析jwt,验签名key的路径
client:
client-id: gateway #获取验签key需要身份认证,这里是网关的clientId
client-secret: 123456 #获取验签key需要身份认证,这里是网关的secret
Spring Cloud微服务安全实战_6-3_jwt认证之网关和服务改造第3张
4,网关作为一个资源服务器,配置其安全配置
/*** 作为一个资源服务器存在
 */@Configuration
@EnableResourceServer
public class GatewaySecurityConfig extendsResourceServerConfigurerAdapter {

    @Override
    public void configure(HttpSecurity http) throwsException {
        http.authorizeRequests()
            .antMatchers("/token/**").permitAll() //放过/token开头的请求,是在申请令牌
.anyRequest().authenticated();
    }
}
5,各个微服务的改造
之前各个微服务需要用到用户信息的时候,在网关上,网关从认证服务器解析令牌,获取到用户信息后,是将用户名以明文的方式放在了请求头里,各个微服务从请求头里获取到明文的username参数,这样是有安全问题的。
此时,各个微服务也需要解析jwt,获取用户信息。所以各个微服务就需要跟网关一样,解析jwt,所以也需要从认证服务器获取验签的key,故需要做和网关一样的配置。
在订单微服务,引入 SpringSecurity-OAuth依赖
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-oauth2</artifactId>
</dependency>
Spring Cloud微服务安全实战_6-3_jwt认证之网关和服务改造第4张

订单微服务也作为资源服务器存在,所以需要给订单微服务打上资源服务器的标记 @EnableResourceServer

Spring Cloud微服务安全实战_6-3_jwt认证之网关和服务改造第5张

在订单微服务,获取用户信息 也要用注解 @AuthenticationPrincipal String username 。
实验:
1,先启动 认证服务器,因为各个微服务启动的时候就会去认证服务器拿jwt验签的key。
2.启动网关。
发现报如下异常 Caused by: org.springframework.web.client.HttpClientErrorException$NotFound: 404 null
Spring Cloud微服务安全实战_6-3_jwt认证之网关和服务改造第6张

Spring Cloud微服务安全实战_6-3_jwt认证之网关和服务改造第7张

这个异常的意思是,在拿jwt验签key的时候,找不到该服务,为什么呢?在认证服务器上,配置jwt tokenStore的时候,需要做一下特殊处理:
需要将
JwtAccessTokenConverter 暴露为Spring的Bean,而且必须为public的。
Spring Cloud微服务安全实战_6-3_jwt认证之网关和服务改造第8张

Spring Cloud微服务安全实战_6-3_jwt认证之网关和服务改造第9张

再次重启认证服务器,重启网关,正常启动。

postman调用网关,获取令牌http://localhost:9070/token/oauth/token

客户端信息表

Spring Cloud微服务安全实战_6-3_jwt认证之网关和服务改造第10张

Spring Cloud微服务安全实战_6-3_jwt认证之网关和服务改造第11张

通过网关,拿access_token去订单服务创建订单http://localhost:9070/order/orders

Spring Cloud微服务安全实战_6-3_jwt认证之网关和服务改造第12张

处理办法:

1,在oauth_client_details表里的orderApp应用的resource_ids 字段里,配置上网关的resourceId,前提是网关代码里也配置了resourceId。这样安全性更高,只是需要维护这些资源服务器id。

Spring Cloud微服务安全实战_6-3_jwt认证之网关和服务改造第13张Spring Cloud微服务安全实战_6-3_jwt认证之网关和服务改造第14张

调用成功

Spring Cloud微服务安全实战_6-3_jwt认证之网关和服务改造第15张

2,如果对安全性要求不高,可以把oauth_client_details表里 orderApp的resource_ids 字段设置为空,这样给orderApp客户端发出的jwt就可以访问任何的微服务了。

Spring Cloud微服务安全实战_6-3_jwt认证之网关和服务改造第16张

在微服务之间传递jwt令牌信息

比如订单微服务调用了加个微服务,那么订单微服务怎么把用户信息传递给价格微服务呢?之前的做法是,将用户信息放在请求头里,进行传递。

其实SpringSecurity-OAuth已经替你把这些事情做好了。可以在微服务之间传递jwt令牌,传过去的jwt会被解析为用户信息。

下面改造订单微服务和价格微服务,在他们之间传递用户信息。

价格微服务也作为资源服务器存在

@SpringBootApplication
@EnableResourceServer//作为资源服务器
public classNbPriceApiApplication {

    public static voidmain(String[] args) {
        SpringApplication.run(NbPriceApiApplication.class, args);
        System.err.println("============= Price Api 启动完成 ============");
    }

}

价格微服务也加入SpringCloud和SpringSecurity-OAuth的依赖

<dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-oauth2</artifactId>
        </dependency>
dependencyManagement里:
<!--spring cloud-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>Greenwich.SR2</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>

价格微服务获取用户信息 : @AuthenticationPrincipal String username

能在微服务之间自动传递jwt令牌信息, 主角就是:OAuth2RestTemplate,它能从请求上下文中拿到jwt 令牌,然后将其放入请求头,在其他微服务里,就可以通过@AuthenticationPrincipal 注解来获得用户信息了。

在订单微服务里配置OAuth2RestTemplate

@Configuration
@SpringBootApplication
@EnableResourceServer//作为资源服务器存在
public classNbOrderApiApplication {

    //声名OAuth2RestTemplate
    //会从请求的上下文里拿到令牌,放到请求头里,发出去。需要两个参数,springboot会自动出入进来
@Bean
    public OAuth2RestTemplate oAuth2RestTemplate(OAuth2ProtectedResourceDetails resource, OAuth2ClientContext context){
        return new OAuth2RestTemplate(resource,context);
    }

    public static voidmain(String[] args) {
        SpringApplication.run(NbOrderApiApplication.class, args);
        System.err.println("============= Order Api 启动完成 ============");
    }

}

随便用某个客户端生成一个jwt令牌

Spring Cloud微服务安全实战_6-3_jwt认证之网关和服务改造第17张

然后通过网关调用创建订单服务器

Spring Cloud微服务安全实战_6-3_jwt认证之网关和服务改造第18张

查看订单服务和价格服务里,是否打印了用户名

订单服务日志,网关已经把jwt传递给了订单服务,而且订单服务把jwt解析成了用户信息

Spring Cloud微服务安全实战_6-3_jwt认证之网关和服务改造第19张

查看价格微服务,看订单服务是否把jwt传给了价格服务

Spring Cloud微服务安全实战_6-3_jwt认证之网关和服务改造第20张

至此,在网关上已经实现了由SpringSecurity-OAuth替我们实现各种认证啊、授权的过滤器。前面系列文章说的都是自己实现这些过滤器,自己实现是为了了解其中的原理。

目前的架构,前面文章说的两个问题:

1,在网关上再去认证服务器验令牌,认证服务器压力变大

解决:token 信息是 jwt,已经自包含身份信息。不用再去认证服务器验令牌。减少了一次请求,网关、认证服务器的压力减小了。

2,明文在微服务之间的请求头里传递用户信息

解决:JWT是自包含身份信息的,用OAuth2RestTemplate发请求,SpringSecurity-OAuth会自动从请求上下文拿到jwt信息,放进请求头,下游微服务拿到后会解析jwt。

到目前来说,各个微服务(包括网关),都是资源服务器,需要在它们配置类上打上@EnableResourceServer 注解,使其成为资源服务器。而且各个资源服务器需要引入SpringCloud的依赖以及spring-cloud-starter-oauth2 依赖。

目前的架构图是这样的

Spring Cloud微服务安全实战_6-3_jwt认证之网关和服务改造第21张

代码:https://github.com/lhy1234/springcloud-security/tree/chapt-6-2-jwt02

免责声明:文章转载自《Spring Cloud微服务安全实战_6-3_jwt认证之网关和服务改造》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇Qt正则表达式类QRegExp(转)Ubuntu 及Ubuntu server版如何启用root用户登录下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

公钥与私钥

在对称加密的时代,加密和解密用的是同一个密钥,这个密钥既用于加密,又用于解密。这样做有一个明显的缺点,如果两个人之间传输文件,两个人都要知道密钥,如果是三个人呢,五个人呢?于是就产生了非对称加密,用一个密钥进行加密(公钥),用另一个密钥进行解密(私钥)。 1.公钥私钥原理 张三有两把钥匙,一把是公钥,另一把是私钥。    张三把公钥送给他的朋友们—-李四、...

flask_jwt_extended 4.0学习

1.前言       在学习flask_jwt_extended插件的时候遇到许多问题,究其原因是因为版本问题,4.0以后的版本在语法上做了许多优化,而我是参考较低版本的flask_jwt_extended学习的,一开始不明白出问题的原因,所以参考了许许多多博友的思路和写法,发现并没有问题,后来想到去看官方的文档,发现了原因所在,以下是4.0版本的api变...

springboot结合jwt实现基于restful接口的身份认证

基于restful接口的身份认证,可以采用jwt的方式实现,想了解jwt,可以查询相关资料,这里不做介绍~ 下面直接看如何实现 1、首先添加jwt的jar包,pom.xml中添加依赖包: <dependency> <groupId>io.jsonwebtoken</groupId>...

如何添加JWT生成的token在请求头中

前言 在我们使用JWT来做用户的验证时,我们登陆生成对应的token,并加入到请求的参数中发送到后台提供相关的权限校验。这个时候我们需要使用到传递请求头参数传递的问题,下面是两种方式。 1.ajax提交方式 1).方法一: $.ajax({ type: "GET", url: "/access/logout/" + userCode, headers: {...

一分钟带你了解JWT认证!

目录 一、JWT简介 二、JWT认证和session认证的区别 三、JWT认证流程 四、JWT组成 五、JWT使用场景 一、JWT简介 JSON Web Token(JWT)是一个开放的标准(RFC 7519),它定义了一个紧凑且自包含的方式,用于在各方之间作为JSON对象安全地传输信息。由于此信息是经过数字签名的,因此可以被验证和信任。 更多信息...

若依官方文档 集成jwt实现登录授权访问,返回SysUser对象更多信息给前端

1:若依版本本次选择 V4.6.1 https://gitee.com/y_project/RuoYi?_from=gitee_search 2:官方插件位置 https://doc.ruoyi.vip/ruoyi/document/cjjc.html#%E9%9B%86%E6%88%90jwt%E5%AE%9E%E7%8E%B0%E7%99%BB%E5%...