因为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. vue结合element-ui实现二级复选框checkbox

    vue结合element-ui实现二级复选框checkbox 话不多说先上效果 交互:1.点击按钮全选,所有的checkbox全部选中:点击清空,所有的checkbox框都不选:点击确定获取选中的ch ...

  2. NOIP2020 浙江 游记

    day - ? 由于 CSP-S 的失利,感觉这一次 NOIP 的心态反而是非常的淡定,感觉反正已经炸过一次了,再炸一次好像也没什么,就抱着这样的心态去考试的. day 1 考试当天起晚了,到考场的时 ...

  3. HashMap相关类:Hashtable、LinkHashMap、TreeMap

    前言 很高兴遇见你~ 在 深入剖析HashMap 文章中我从散列表的角度解析了HashMap,在 深入解析ConcurrentHashMap:感受并发编程智慧 解析了ConcurrentHashMap ...

  4. react中对内容点击复制

    在react中一个标签内,点击这个标签直接复制标签内的内容 如图,我的需求是点击id这个标签实现对id的一键复制,所以请看copyHander函数 先创建一个Range对象,Range 对象表示文档的 ...

  5. 史上最全单链表的增删改查反转等操作汇总以及5种排序算法(C语言)

    目录 1.准备工作 2.创建链表 3.打印链表 4.在元素后面插入元素 5.在元素前面增加元素 6.删除链表元素,要注意删除链表尾还是链表头 7.根据传入的数值查询链表 8.修改链表元素 9.求链表长 ...

  6. 服务器标配 SSH 协议,你了解多少?

    年初,新冠肺炎疫情的出现,全国数千万名员工在家远程办公,使用个人设备通过家庭网络访问公司资料.因此,IT 安全团队面临了众多新挑战:如何实施更加安全的身份验证方案,以确保只有授权人员和设备才能访问公司 ...

  7. java.net.BindException:Problem binding to [hostname:8088]地址已在使用

    异常提示端口号被占用 查找被占用的端口 netstat -tln netstat -tln | grep 8083 netstat -tln ## 查看端口使用情况,而netstat -tln | g ...

  8. windows宿主机访问ubuntu虚拟机中的docker服务

    查看docker容器地址和虚拟机地址 windows主机中添加路由 #route -p add 172.17.0.0 mask 255.255.0.0 虚拟机地址 route -p add 172.1 ...

  9. Kafka客户端编程入门介绍

    1.maven依赖 <dependency> <groupId>org.apache.kafka</groupId> <artifactId>kafka ...

  10. Unity 2017 Scene界面与Game界面显示不同/过于灰暗的解决办法

    场景界面的显示过于灰暗,严重影响工作心情. 切换到游戏界面时的颜色. 只要将场景中全部摄像机的[Allow HDR]取消勾选即可.