Spring Security + OAuth2.0 构建微服务统一认证解决方案(三)

搭建过程可以分为以下几步

  1. 构建简单的Spring Security + OAuth2.0 认证服务
  2. 优化认证服务(使用JWT技术加强token,自定义auth接口以及返回结果)
  3. 配置gateway服务完成简单鉴权功能
  4. 优化gateway配置(添加复杂鉴权逻辑等等)

(三)配置gateway服务完成JWT简单鉴权功能

之前的网关服务仅仅用做请求的路由转发。现在对网关服务进行,对请求中携带的token进行鉴权。

一. 配置相关依赖

导入spring security和oauth相关依赖,以及JWT相关依赖

<dependency>
    <groupId>org.springframework.security</groupId>
    <artifactId>spring-security-config</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.security</groupId>
    <artifactId>spring-security-oauth2-client</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.security</groupId>
    <artifactId>spring-security-oauth2-resource-server</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.security</groupId>
    <artifactId>spring-security-oauth2-jose</artifactId>
</dependency>
 
<dependency>
    <groupId>com.nimbusds</groupId>
    <artifactId>nimbus-jose-jwt</artifactId>
    <version>9.10.1</version>
</dependency>

要注意的是导入 nimbus-jose-jwt 这个包时,在启动时可能会出现冲突的奇怪问题,详情如下(当时用的是8.17版本)

更新包版本,换成9.10.1就没这个问题了

二. 配置JWT解码需要的公钥获取接口

之前在Auth服务中用私钥在JWT中创建了签名,由此我们在验证时需要用公钥对Token进行验证,防止伪造Token。

Auth服务提供公钥接口

在Auth服务中,由于之前创建好了RSA 密钥的 KeyPair 的 Bean,可以很方便地创建一个接口返回公钥信息

@RestController
public class RSAController {
 
    @Autowired
    private KeyPair keyPair;
 
    @GetMapping("/rsa/publicKey")
    public Map<String, Object> getKey() {
        RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic();
        RSAKey key = new RSAKey.Builder(publicKey).build();
        return new JWKSet(key).toJSONObject();
    }
}

也要记得在spring security的配置中放开权限

public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
 
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests()
                // 放开接口权限
                .antMatchers("/rsa/publicKey").permitAll()
                .anyRequest().authenticated();
    }
    ......
}

gateway服务配置公钥获取url

在yaml中进行配置即可,之后配置好JWT解码,框架会自动去请求公钥验证

spring:
  security:
    oauth2:
      resourceserver:
        jwt:
          jwk-set-uri: 'http://localhost:8401/rsa/publicKey'

三. 启用JWT验证

使用 @EnableWebFluxSecurity 注解开启 WebFlux
在config中启用jwt验证

@Configuration
@EnableWebFluxSecurity
public class ResourceServerConfig {
 
    @Bean
    public SecurityWebFilterChain springSecurityFilterChain(ServerHttpSecurity http) {
        // 开启jwt验证
        http.oauth2ResourceServer().jwt();
        return http.build();
    }
}

四. 测试结果

1) 放入之前过期的accessToken请求某接口
这里的Token前缀加上了“Bearer ”,用于定义该Authorization的规范。可以看到结果返回401,错误信息是因为token过期

2)放入错误token
从之前Token中删去一些字符使其失效,再次请求
可以看到返回401,错误信息是token无效,解析失败。

3)放入正确Token
新生成一个token,放入Authorization字段中进行请求,看到通过了校验,可以正常路由并返回结果

五. 后续工作

这只是一个超级简单的gateway鉴权,且只有Authorization字段前缀为“Bearer ”时才开启校验,否则不校验。
如下,随便输入字符串也可以得到结果。

由此,后续可以将鉴权逻辑进行优化

  • 增加筛选,将Authorization字段前缀非“Bearer ”开头的请求拦截
  • OPTIONS(预检)请求和白名单路径直接放行
  • 给URL设置用户访问权限并校验
  • 添加自定义gateway filter

Spring Security + OAuth2.0 构建微服务统一认证解决方案(一)
Spring Security + OAuth2.0 构建微服务统一认证解决方案(二)
Spring Security + OAuth2.0 构建微服务统一认证解决方案(四)
github 仓库

posted @ 2021-11-14 23:18  BuptWade  阅读(1450)  评论(0编辑  收藏  举报