springBoot从2.x升级到3.x后Oauth 客户端模式兼容以前代码处理
这样就能兼容spring-security-oauth2的相关配置了,注意client_id,clientSecret需要使用以前的配置(目前代码是通过读库处理)由于以前使用spring-security-oauth2时指定了获取token的访问地址为/access-token。升级为springboot3后已经无法使用spring-security-oauth2,需要使用。原springboot
·
原springboot使用的spring-security-oauth2
部分代码如下
@Configuration
@EnableWebSecurity
public class SpringSecurityConfig extends WebSecurityConfigurerAdapter {
@Resource
private UserDetailsService userDetailsService; //
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
// 读取用户信息进行认证
auth.userDetailsService(userDetailsService);
}
// password 模式需要此 bean
@Bean
@Override
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
//关闭 csrf 攻击
@Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable();
}
}
@Configuration
// 开启了认证服务器
@EnableAuthorizationServer
public class AuthorizationServerConfig extends AuthorizationServerConfigurerAdapter {
@Resource // 1. 数据源
private DataSource dataSource;
@Bean // 1. 客户端使用 jdbc 管理
public ClientDetailsService jdbcClientDetailsService() {
return new JdbcClientDetailsService(dataSource);
}
/**
* 1. 配置被允许访问此认证服务器的客户端信息: 数据库方式
* 如:门户客户端,后台客户端
*/
@Override
public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
// jdbc 管理客户端
clients.withClientDetails(jdbcClientDetailsService());
}
// 2. 在 SpringSecurityConfig 中添加到容器了, 密码模式需要
@Resource
private AuthenticationManager authenticationManager;
// 不驗證登錄密碼
@Resource
private UserDetailsService userDetailsService;
// token管理方式,引用 JwtTokenStoreConfig 配置的
@Resource
private TokenStore tokenStore;
// jwt 转换器
@Resource
private JwtAccessTokenConverter jwtAccessTokenConverter;
// 注入增强器
@Resource
private TokenEnhancer jwtTokenEnhancer;
/**
* 关于认证服务器端点配置
* @param endpoints
* @throws Exception
*/
@Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
// 密码模块必须使用这个authenticationManager实例
endpoints.authenticationManager(authenticationManager);
// 刷新令牌需要 使用userDetailsService,不刷新令牌
endpoints.userDetailsService(userDetailsService);
// 令牌管理方式
endpoints.tokenStore(tokenStore).accessTokenConverter(jwtAccessTokenConverter);
// 添加增强器
TokenEnhancerChain enhancerChain = new TokenEnhancerChain();
// 组合 增强器和jwt转换器
List<TokenEnhancer> enhancerList = new ArrayList<>();
enhancerList.add(jwtTokenEnhancer);
enhancerList.add(jwtAccessTokenConverter);
enhancerChain.setTokenEnhancers(enhancerList);
// 将认证信息的增强器添加到端点上
endpoints.tokenEnhancer(enhancerChain).accessTokenConverter(jwtAccessTokenConverter);
endpoints.pathMapping("/oauth/token", "/access-token");
}
@Override
public void configure(AuthorizationServerSecurityConfigurer security) {
// /oauth/check_token 解析令牌,默认情况 下拒绝访问
security.checkTokenAccess("permitAll()");
// .checkTokenAccess("isAuthenticated()");
}
}
依赖如下
<dependency>
<groupId>org.springframework.security.oauth</groupId>
<artifactId>spring-security-oauth2</artifactId>
<version>${spring.security.oauth.version}</version>
</dependency>
升级为springboot3后已经无法使用spring-security-oauth2,需要使用
spring-boot-starter-oauth2-authorization-server
依赖如下
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-oauth2-authorization-server</artifactId>
<version>3.2.3</version>
</dependency>
主要代码如下
@Configuration
public class AuthorizationServerConfig {
/**
* 授权服务器 SecurityFilterChain
*/
@Bean
@Order(Ordered.HIGHEST_PRECEDENCE)
public SecurityFilterChain authorizationServerSecurityFilterChain(HttpSecurity http)
throws Exception {
OAuth2AuthorizationServerConfiguration.applyDefaultSecurity(http);
http.getConfigurer(OAuth2AuthorizationServerConfigurer.class)
.oidc(Customizer.withDefaults()); // Enable OpenID Connect 1.0
http
// Redirect to the login page when not authenticated from the
// authorization endpoint
.exceptionHandling((exceptions) -> exceptions
.authenticationEntryPoint(
new LoginUrlAuthenticationEntryPoint("/login"))
)
// Accept access tokens for User Info and/or Client Registration
.oauth2ResourceServer(OAuth2ResourceServerConfigurer::jwt);
return http.build();
}
/**
* 客户端配置,基于内存
*/
@Bean
public RegisteredClientRepository registeredClientRepository(JdbcTemplate jdbcTemplate) {
BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder();
CpParticipantEntity cpEntity = ParticipantUtils.getCRPObj();
String clientId = cpEntity.getClientId();
String secret = AESCbcUtil.decryptBase64(cpEntity.getClientSecret(), Const.Common.AES_PWD);
RegisteredClient oidcClient = RegisteredClient.withId(UUID.randomUUID().toString())
.clientId(clientId)
.clientName(clientId)
.clientIdIssuedAt(Instant.now())
.clientSecret(passwordEncoder.encode(secret))
.clientSecretExpiresAt(Instant.now().plus(14, ChronoUnit.DAYS))
.clientAuthenticationMethod(ClientAuthenticationMethod.CLIENT_SECRET_BASIC)
.clientAuthenticationMethod(ClientAuthenticationMethod.CLIENT_SECRET_POST)
.authorizationGrantType(AuthorizationGrantType.CLIENT_CREDENTIALS)
.authorizationGrantType(AuthorizationGrantType.REFRESH_TOKEN)
.postLogoutRedirectUri("http://127.0.0.1:8081/logout")
.scope("message.read")
.clientSettings(ClientSettings.builder().requireAuthorizationConsent(false).build())
.tokenSettings(TokenSettings.builder()
//access token 有效期
.accessTokenTimeToLive(Duration.ofMinutes(60))
.build())
.build();
return new InMemoryRegisteredClientRepository(oidcClient);
//);
//return registeredClientRepository;
}
/**
* 默认发放令牌
*
* @return
*/
@Bean
public JWKSource<SecurityContext> jwkSource() {
KeyPair keyPair = generateRsaKey();
RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic();
RSAPrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate();
RSAKey rsaKey = new RSAKey.Builder(publicKey)
.privateKey(privateKey)
.keyID(UUID.randomUUID().toString())
.build();
JWKSet jwkSet = new JWKSet(rsaKey);
return new ImmutableJWKSet<>(jwkSet);
}
private static KeyPair generateRsaKey() {
KeyStoreKeyFactory factory = new KeyStoreKeyFactory(new ClassPathResource("hwss.jks"), "123456".toCharArray());
return factory.getKeyPair("hwss");
/*KeyPair keyPair;
try {
KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
keyPairGenerator.initialize(2048);
keyPair = keyPairGenerator.generateKeyPair();
} catch (Exception ex) {
throw new IllegalStateException(ex);
}
return keyPair;*/
}
@Bean
public JwtDecoder jwtDecoder(JWKSource<SecurityContext> jwkSource) {
return OAuth2AuthorizationServerConfiguration.jwtDecoder(jwkSource);
}
@Bean
public AuthorizationServerSettings authorizationServerSettings() {
return AuthorizationServerSettings.builder().build();
}
}
@EnableWebSecurity
@Configuration(proxyBeanMethods = false)
public class DefaultSecurityConfig {
@Bean
@Order(2)
public SecurityFilterChain defaultSecurityFilterChain(HttpSecurity http)
throws Exception {
http
.authorizeHttpRequests((authorize) -> authorize
.requestMatchers(new AntPathRequestMatcher("/*/**")).permitAll()
.anyRequest().authenticated()
)
.cors(Customizer.withDefaults())
.csrf((csrf) -> csrf.disable())
.formLogin(Customizer.withDefaults())
;
return http.build();
}
@Bean
public UserDetailsService userDetailsService() {
UserDetails userDetails = User.withDefaultPasswordEncoder()
.username("user")
.password("password")
.roles("USER")
.build();
return new InMemoryUserDetailsManager(userDetails);
}
}
由于以前使用spring-security-oauth2时指定了获取token的访问地址为/access-token
,更新后无法使用该地址进行访问,故添加controller进行转发处理
代码如下
@RequestMapping("/access-token")
public void forwardToTargetPage(HttpServletRequest request, HttpServletResponse response) {
try {
request.getRequestDispatcher("/oauth2/token").forward(request, response);
} catch (Exception e) {
e.printStackTrace();
}
}
这样就能兼容spring-security-oauth2的相关配置了,注意client_id,clientSecret需要使用以前的配置(目前代码是通过读库处理)

魔乐社区(Modelers.cn) 是一个中立、公益的人工智能社区,提供人工智能工具、模型、数据的托管、展示与应用协同服务,为人工智能开发及爱好者搭建开放的学习交流平台。社区通过理事会方式运作,由全产业链共同建设、共同运营、共同享有,推动国产AI生态繁荣发展。
更多推荐
所有评论(0)