因为Spring Cloud 2020.0.0和Spring Boot2.4.1版本升级比较大,所以把我接入过程中的一些需要注意的地方告诉大家

我使用的版本是Spring boot 2.4.1+Spring Cloud 2020.0.0

我的架构是Gateway做Resource Server,然后服务内部不暴露到外网,微服务之间调用不需要再做验证。

而且为了减少请求Auth Server采用JWT方式

完全使用Spring Security的机制

最新的版本里面取消了org.springframework.cloud:spring-cloud-starter-oauth2

我使用了官方最新推荐集成Oauth2.0

AuthServer:
implementation 'org.springframework.security.oauth.boot:spring-security-oauth2-autoconfigure'
implementation 'org.springframework.security:spring-security-oauth2-jose'
Gateway:
implementation 'org.springframework.security:spring-security-config'
implementation 'org.springframework.security:spring-security-oauth2-resource-server'
implementation 'org.springframework.security:spring-security-oauth2-jose'

取消Ribbon之后使用

implementation 'org.springframework.cloud:spring-cloud-starter-loadbalancer'

下面把关键文件的源码粘贴出来

网关服务器

Gateway:

/**
* 资源服务器配置
* @author Mikey Huang
* @date 2020/12/28
*/
@Configuration
@EnableWebFluxSecurity
@EnableReactiveMethodSecurity
public class ResourceServerConfig {
/**
* 注册安全验证规则
* 配置方式与HttpSecurity基本一致
*/
@Bean
public SecurityWebFilterChain securityWebFilterChain(ServerHttpSecurity http) { //定义SecurityWebFilterChain对安全进行控制,使用ServerHttpSecurity构造过滤器链;
http.authorizeExchange()
//注意! hasrole里面的值必须和jwt负载的值一致
.pathMatchers("/user/user/login").hasRole("ROLE_ADMIN")
.pathMatchers("/user/user/hello").hasRole("ROLE_USER")
.pathMatchers("/auth/oauth/token", "/auth/oauth/check_token").permitAll()
.anyExchange().authenticated()
.and().csrf().disable();
http.oauth2ResourceServer().jwt().jwtAuthenticationConverter(jwtAuthenticationConverter());
return http.build();
} /**
* 使用ROLE来做权限验证,默认是SCOPE
* @return
*/
@Bean
public Converter<Jwt, ? extends Mono<? extends AbstractAuthenticationToken>> jwtAuthenticationConverter() {
JwtGrantedAuthoritiesConverter jwtGrantedAuthoritiesConverter = new JwtGrantedAuthoritiesConverter();
jwtGrantedAuthoritiesConverter.setAuthorityPrefix("ROLE_");
jwtGrantedAuthoritiesConverter.setAuthoritiesClaimName("authorities");
JwtAuthenticationConverter jwtAuthenticationConverter = new JwtAuthenticationConverter();
jwtAuthenticationConverter.setJwtGrantedAuthoritiesConverter(jwtGrantedAuthoritiesConverter);
return new ReactiveJwtAuthenticationConverterAdapter(jwtAuthenticationConverter);
}
}
server:
port: 8080
spring:
application:
name: gateway
security:
oauth2:
resourceserver:
jwt:
#配置RSA的公钥访问地址
jwk-set-uri: 'http://localhost:8081/.well-known/jwks.json'
cloud:
nacos:
discovery:
server-addr: localhost:8848
gateway:
discovery:
locator:
enabled: true
routes:
- id: auth
uri: lb://auth
predicates:
- Path=/auth/**
filters:
- StripPrefix=1
- id: user
uri: lb://user
predicates:
- Path=/user/**
filters:
- StripPrefix=1

授权服务器

AuthServer:

/**
* 认证服务器配置
* @author Mikey Huang
* @date 2020/12/28
*/
@Configuration
@EnableAuthorizationServer
public class AuthorizationServerConfig extends AuthorizationServerConfigurerAdapter {
private final AuthenticationManager authenticationManager;
private final JwtTokenEnhancer jwtTokenEnhancer;
private final ApplicationContext context; public AuthorizationServerConfig(AuthenticationManager authenticationManager, JwtTokenEnhancer jwtTokenEnhancer,
ApplicationContext context) {
this.authenticationManager = authenticationManager;
this.jwtTokenEnhancer = jwtTokenEnhancer;
this.context = context;
} @Override
public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
// 内存中创建一个客户端
clients.inMemory()
.withClient("client-app")
.secret("123456")
.authorizedGrantTypes("password", "refresh_token")
.scopes("all"); } @Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
TokenEnhancerChain enhancerChain = new TokenEnhancerChain();
List<TokenEnhancer> delegates = new ArrayList<>();
delegates.add(jwtTokenEnhancer);
delegates.add(accessTokenConverter());
// 配置JWT的内容增强器
enhancerChain.setTokenEnhancers(delegates);
endpoints.authenticationManager(authenticationManager)
.accessTokenConverter(accessTokenConverter())
.tokenEnhancer(enhancerChain); } @Override
public void configure(AuthorizationServerSecurityConfigurer security) throws Exception {
security.allowFormAuthenticationForClients()
.checkTokenAccess("isAuthenticated()"); } @Bean
public JwtAccessTokenConverter accessTokenConverter() {
JwtAccessTokenConverter jwtAccessTokenConverter = new JwtAccessTokenConverter();
jwtAccessTokenConverter.setKeyPair(keyPair());
return jwtAccessTokenConverter;
} /**
* 通过读取key store的配置构造
* @return
*/
@Bean
public KeyPair keyPair(){
AuthorizationServerProperties properties = authorizationServerProperties();
Resource keyStore = context
.getResource(properties.getJwt().getKeyStore());
char[] keyStorePassword = properties.getJwt().getKeyStorePassword()
.toCharArray();
KeyStoreKeyFactory keyStoreKeyFactory = new KeyStoreKeyFactory(keyStore,
keyStorePassword);
String keyAlias = properties.getJwt().getKeyAlias();
char[] keyPassword = Optional
.ofNullable(properties.getJwt().getKeyPassword())
.map(String::toCharArray).orElse(keyStorePassword);
return keyStoreKeyFactory.getKeyPair(keyAlias, keyPassword);
} @Bean
public AuthorizationServerProperties authorizationServerProperties() {
return new AuthorizationServerProperties();
}
}
/**
* Spring Security配置
* @author Mikey Huang
* @date 2020/12/28
*/
@Configuration
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter { @Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.antMatchers("/oauth/**", "/.well-known/jwks.json").permitAll()
.anyRequest().authenticated().and().csrf().disable();
} @Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
//内存中创建两个用户,两个不同的role用来测试权限
auth.inMemoryAuthentication()
.passwordEncoder(passwordEncoder())
.withUser("mikey").password("123456").roles("ADMIN")
.and()
.withUser("sirius").password("654321").roles("USER");
} @Bean
@Override
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
} @Bean
public PasswordEncoder passwordEncoder() {
// return new BCryptPasswordEncoder();
// 方便测试,暂时不加密
return NoOpPasswordEncoder.getInstance();
}
}
/**
* @author Mikey Huang
* @date 2020/12/28
*/
@FrameworkEndpoint
public class JwkSetEndpoint {
private final KeyPair keyPair; @Autowired
public JwkSetEndpoint(KeyPair keyPair) {
this.keyPair = keyPair;
} @GetMapping("/.well-known/jwks.json")
@ResponseBody
public Map<String, Object> getKey() {
RSAPublicKey publicKey = (RSAPublicKey) this.keyPair.getPublic();
RSAKey key = new RSAKey.Builder(publicKey).build();
return new JWKSet(key).toJSONObject();
}
}
/**
* jwt token增强
* @author Mikey Huang
* @date 2020/12/28
*/
@Component
public class JwtTokenEnhancer implements TokenEnhancer {
@Override
public OAuth2AccessToken enhance(OAuth2AccessToken accessToken, OAuth2Authentication authentication) {
User user = (User) authentication.getPrincipal();
Map<String, Object> info = new HashMap<>();
//存入需要的信息,例如把密码设置到JWT中
info.put("password", user.getPassword());
((DefaultOAuth2AccessToken) accessToken).setAdditionalInformation(info);
return accessToken;
}
}
server:
port: 8081 spring:
application:
name: auth
cloud:
nacos:
discovery:
server-addr: localhost:8848 security:
oauth2:
authorization:
jwt:
key-store: classpath:mikey.jks
key-store-password: 123456
key-alias: mikey
key-password: 123456

测试截图

如果需要测试权限可以用创建的两个账号来分别调用User的两个接口,可以看到ROLE的效果







项目代码

最新最简洁Spring Cloud Oauth2.0 Jwt 的Security方式的更多相关文章

  1. Spring Cloud OAuth2.0 微服务中配置 Jwt Token 签名/验证

    关于 Jwt Token 的签名与安全性前面已经做了几篇介绍,在 IdentityServer4 中定义了 Jwt Token 与 Reference Token 两种验证方式(https://www ...

  2. SpringCloud(10)使用Spring Cloud OAuth2和JWT保护微服务

    采用Spring Security AOuth2 和 JWT 的方式,避免每次请求都需要远程调度 Uaa 服务.采用Spring Security OAuth2 和 JWT 的方式,Uaa 服务只验证 ...

  3. 使用Spring Cloud OAuth2和JWT保护微服务

    采用Spring Security AOuth2 和 JWT 的方式,避免每次请求都需要远程调度 Uaa 服务.采用Spring Security OAuth2 和 JWT 的方式,Uaa 服务只验证 ...

  4. Spring cloud oauth2.0 access_token 永不失效设置方法

    在AuthorizationServerConfigurerAdapter,重写一个TokenServices,注意这里的@Primary 非常重要,否则会有3个同类型的Bean,无法注入,会抛出以下 ...

  5. 基于spring boot2.0+spring security +oauth2.0+ jwt微服务架构

    github地址:https://github.com/hankuikuide/microservice-spring-security-oauth2 项目介绍 该项目是一个演示项目,主要演示了,基于 ...

  6. 微信授权就是这个原理,Spring Cloud OAuth2 授权码模式

    上一篇文章Spring Cloud OAuth2 实现单点登录介绍了使用 password 模式进行身份认证和单点登录.本篇介绍 Spring Cloud OAuth2 的另外一种授权模式-授权码模式 ...

  7. vue+uni-app商城实战 | 第一篇:【有来小店】微信小程序快速开发接入Spring Cloud OAuth2认证中心完成授权登录

    一. 前言 本篇通过实战来讲述如何使用uni-app快速进行商城微信小程序的开发以及小程序如何接入后台Spring Cloud微服务. 有来商城 youlai-mall 项目是一套全栈商城系统,技术栈 ...

  8. Spring Cloud 2020.0.0正式发布,再见了Netflix

    目录 ✍前言 版本约定 ✍正文 Spring Cloud版本管理 与Spring Boot版本对应关系 当前支持的版本 阻断式升级(不向下兼容) 1.再见了,Netflix Netflix组件替代方案 ...

  9. Spring Cloud 2020.0.0 正式发布,全新颠覆性版本!

    Spring Cloud 2020.0.0 没错,Spring Cloud 2020.0.0 正式发布了: 感谢Java技术栈群友通知,想入群的在公众号Java技术栈后台回复:wx,正在使用 Spri ...

随机推荐

  1. vertical-align什么时候使用?常用的值分别有什么作用?

    设置元素的垂直对齐方式 常用的值: 1.baseline:默认.元素放置在父元素的基线上. 2.sub:垂直对齐文本的下标. 3.super:垂直对齐文本的上标 4.top:把元素的顶端与行中最高元素 ...

  2. 【题解】「UVA681」Convex Hull Finding

    更改了一下程序的错误. Translation 找出凸包,然后逆时针输出每个点,测试数据中没有相邻的边是共线的.多测. Solution 首先推销一下作者的笔记 由此进入>>> ( ...

  3. BJOI2016 回转寿司

    题目链接 Description 给定一个长度为 \(N\) 的序列 \(a\),和一个区间 \([L, R]\). 求多少连续子序列的权值和在区间内,即满足 \(1 \le i \le j \le ...

  4. 题解-MtOI2019 幽灵乐团

    题面 MtOI2019 幽灵乐团 给定 \(p\),\(Cnt\) 组测试数据,每次给 \(a,b,c\),求 \[\prod_{i=1}^a\prod_{j=1}^b\prod_{k=1}^c\le ...

  5. Angular:组件之间的通信@Input、@Output和ViewChild

    ①父组件给子组件传值 1.父组件: ts: export class HomeComponent implements OnInit { public hxTitle = '我是首页的头部'; con ...

  6. ORA-29701: unable to connect to Cluster Synchronization Service

    修改主机名后,has无法启动,将has启动之后,尝试ASMCA,出现如图提示: 再尝试登陆asm实例,出现日下提示: [oracle@edgzrip2-+ASM ~]$ sqlplus / as sy ...

  7. java中什么是对象,什么是对象引用

    在Java语句中,我们都会用到"=",但是这个"="的意义大部分人都没有一个清楚明确的认知 例如:Student a = new Student(); Stud ...

  8. 精尽Spring MVC源码分析 - HandlerMapping 组件(二)之 HandlerInterceptor 拦截器

    该系列文档是本人在学习 Spring MVC 的源码过程中总结下来的,可能对读者不太友好,请结合我的源码注释 Spring MVC 源码分析 GitHub 地址 进行阅读 Spring 版本:5.2. ...

  9. mini-web框架-装饰器-总结2(5.3.2)

    @ 目录 1.说明 2.代码 关于作者 1.说明 多级装饰器嵌套 带参数的装饰器 这里打印print(index) 会在函数定义的时候@test(222) 就被调用,返回一个test2继续装饰 2.代 ...

  10. 怎样用Java 8优雅的开发业务

    怎样用Java 8优雅的开发业务 目录 怎样用Java 8优雅的开发业务 函数式编程 流式编程 基本原理 案例 优雅的空处理 新的并发工具类CompletableFuture 单机批处理多线程执行模型 ...