技术栈
SpringBoot 3.3.1
SpringSecurity 6.3.1
Spring Security OAuth2 Server 1.3.1
架构需求
OAuth2 配置数据库,把client信息和token信息保存到数据库中,以免宕机重启后token失效。
jwt token有效时间设置
资源服务器加请求日志配置,记录所有请求资源记录。
项目配置
POM核心配置
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-oauth2-authorization-server</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
<dependency>
<groupId>com.mysql</groupId>
<artifactId>mysql-connector-j</artifactId>
<scope>runtime</scope>
</dependency>
授权服务器主要依赖于spring-security-oauth2-authorization-server-1.3.1.jar
代码配置
数据库配置好后,Spring会构建一个JdbcTemplate到容器中。把JdbcTemplate给JdbcRegisteredClientRepository
@Bean
public RegisteredClientRepository registeredClientRepository(PasswordEncoder passwdEncoder) {
ClientSettings clientSetting=ClientSettings.builder().requireAuthorizationConsent(true).build();
TokenSettings tokenSetting=TokenSettings.builder()
.authorizationCodeTimeToLive(Duration.ofSeconds(30))
.accessTokenTimeToLive(Duration.ofMinutes(10))
.refreshTokenTimeToLive(Duration.ofHours(20))
.reuseRefreshTokens(false)//如果为true表示refreshToken可以重复使用,false则每次返回新的
.accessTokenFormat(OAuth2TokenFormat.SELF_CONTAINED)
.build();
RegisteredClient oidcClient = RegisteredClient.withId(UUID.randomUUID().toString())
.clientId("clientid")
.clientSecret(passwdEncoder.encode("client_secret"))如果是CLIENT_SECRET_POST才会用到
.clientAuthenticationMethod(ClientAuthenticationMethod.CLIENT_SECRET_BASIC) //不建议使用,安全性低
.clientAuthenticationMethod(ClientAuthenticationMethod.CLIENT_SECRET_POST) //不建议使用,安全性低
.clientAuthenticationMethod(ClientAuthenticationMethod.NONE)
.authorizationGrantType(AuthorizationGrantType.AUTHORIZATION_CODE)
.authorizationGrantType(AuthorizationGrantType.CLIENT_CREDENTIALS)
.authorizationGrantType(AuthorizationGrantType.REFRESH_TOKEN)
.redirectUri("http://localhost:8010/login/oauth2/code/authcode")
.postLogoutRedirectUri("http://localhost:8010/index")
.scope(OidcScopes.OPENID)
.scope(OidcScopes.PROFILE)
.clientSettings(clientSetting)
.tokenSettings(tokenSetting)
.build();
JdbcRegisteredClientRepository jdbcRegister=new JdbcRegisteredClientRepository(jdbcTemplate);
if(null==jdbcRegister.findByClientId(oidcClient.getClientId())) {
jdbcRegister.save(oidcClient);
}
return jdbcRegister;
}
这样就可以从数据库中获取客户端信息了。
refresh_token的时间要比access_token的时间长,但一定要大于60秒。因为OAuth2Client程序会判断,会提前60秒进行refresh token。就会使用refresh_token重新获取。
reuseRefreshToken=true的话,refresh_token会被多次使用。建议每次换一个新的,这样更安全。
具体代码GIT地址:demo_05