总结
前言

最近ChatGPT异常火爆,看看它能不能帮我写完这个公众号。
看来暂时还不行,那只能亲自编辑了。
首先只需要引入
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-oauth2-authorization-server</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-config</artifactId>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-web</artifactId>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-oauth2-core</artifactId>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-oauth2-jose</artifactId>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-oauth2-resource-server</artifactId>
<scope>compile</scope>
</dependency>
本文以开源项目PIG 基于新版的认证体系来讲解。大概感兴趣可以体验一下。
1.新旧版本对比
新版组件Spring Authorization Server 不再提供显示tokenEndpoint类,用户可以自己去定义自己的登录端点。
1.1 tokenEndpoint对比
我们先看老板本的tokenEndPoint提供了哪些方法
处理获取token的方法外,其他都是异常的处理。
我们再看看新版的,新版没有tokenEndPoint了,换成了OAuth2TokenEndpointConfigurer,成了一个名副其实的配置类。
将token相关的个性化配置全部收集在了一起。比如token转化accessTokenRequestConverter,认证管理器AuthenticationProvider,请求匹配器RequestMatcher等等。
对比我们在Spring Security Oauth2中更加清晰明了。在Spring Security Oauth2中, 获取token整个流程为tokenEndpoint–>tokenGranter–>AuthenticationManager–>ProviderManager–>Tokenservice –>AccessTokenConverter–>token。
你只有对源码非常清楚的情况下才知道哪些可以扩展。而且每个核心类之间彼此没有很强的关联。
1.2 tokenEndpoint token端口相关配置
在Spring Authorization Server中,默认提供了如下端口的配置
public final class AuthorizationServerSettings extends AbstractSettings {
public static Builder builder() {
return new Builder()
.authorizationEndpoint("/oauth2/authorize")
.tokenEndpoint("/oauth2/token")
.jwkSetEndpoint("/oauth2/jwks")
.tokenRevocationEndpoint("/oauth2/revoke")
.tokenIntrospectionEndpoint("/oauth2/introspect")
.oidcClientRegistrationEndpoint("/connect/register")
.oidcUserInfoEndpoint("/userinfo");
}
public final class AuthorizationServerSettings extends AbstractSettings {
public static Builder builder() {
return new Builder()
.authorizationEndpoint("/oauth2/authorize")
.tokenEndpoint("/oauth2/token")
.jwkSetEndpoint("/oauth2/jwks")
.tokenRevocationEndpoint("/oauth2/revoke")
.tokenIntrospectionEndpoint("/oauth2/introspect")
.oidcClientRegistrationEndpoint("/connect/register")
.oidcUserInfoEndpoint("/userinfo");
}
以上这些端口,组件都无需定义具体的api.
当然如果你想修改这些端口,只需自定义即可。如改成/oauth2/token/test
@Bean
public AuthorizationServerSettings authorizationServerSettings() {
return AuthorizationServerSettings
.builder()
.tokenEndpoint("/oauth2/token/test")
.build();
}
获取token的请求便是
1.3. Oauth2协议其他配置对比
1.3.1 资源服务器配置
@Configuration
@EnableResourceServer
protected class ResourceServerConfiguration extends ResourceServerConfigurerAdapter {
@Override
public void configure(HttpSecurity http) throws Exception {
http
.csrf()
.disable()
// 开启跨域
.cors().and()
.exceptionHandling()
.authenticationEntryPoint(customerAuthenticationEntryPoint())
.accessDeniedHandler(customerOAuth2AccessDeniedHandler())
.and()
.authorizeRequests()
.antMatchers(
"/oauth/**",
...
)
.permitAll()
.anyRequest()
.authenticated();
}
新版本只需配置过滤器链SecurityFilterChain(PIG 项目配置,和官网差不多)
@Bean
SecurityFilterChain defaultSecurityFilterChain(HttpSecurity http) throws Exception {
http
// 开放自定义的部分端点
.authorizeRequests(authorizeRequests -> authorizeRequests.antMatchers("/token/*").permitAll()
.anyRequest().authenticated())
.headers()
.frameOptions()
.sameOrigin()// 避免iframe同源无法登录
.and()
// 表单登录个性化
.apply(new FormIdentityLoginConfigurer());
// 处理 UsernamePasswordAuthenticationToken
http.authenticationProvider(new PigDaoAuthenticationProvider());
return http.build();
}
public final class FormIdentityLoginConfigurer
extends AbstractHttpConfigurer<FormIdentityLoginConfigurer, HttpSecurity> {
@Override
public void init(HttpSecurity http) throws Exception {
http.formLogin(formLogin -> {
formLogin.loginPage("/token/login");
formLogin.loginProcessingUrl("/token/form");
formLogin.failureHandler(new FormAuthenticationFailureHandler());
}).logout() // SSO登出成功处理
.logoutSuccessHandler(new SsoLogoutSuccessHandler()).deleteCookies("JSESSIONID")
.invalidateHttpSession(true).and().csrf().disable();
}
} .logoutSuccessHandler(new SsoLogoutSuccessHandler()).deleteCookies("JSESSIONID")
.invalidateHttpSession(true).and().csrf().disable();
}
}
1.3.2 认证服务器配置
在老版本SpringSecurityOauth2,需要继承AuthorizationServerConfigurerAdapter
@Configuration
@EnableAuthorizationServer
protected class AuthorizationServerConfiguration extends AuthorizationServerConfigurerAdapter {
@Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
endpoints
//❶token存储
.tokenStore(tokenStore())
//❷异常翻译器
.exceptionTranslator(webResponseExceptionTranslator)
//❸token转化器
.accessTokenConverter(accessTokenConverter())
//❹自省处理器
.userDetailsService(customerUserDetailService)
//❺认证管理器
.authenticationManager(authenticationManager);
}
新版本同样只需配置过滤器链SecurityFilterChain(同样以PIG 项目配置,和官网差不多)
@Bean
@Order(Ordered.HIGHEST_PRECEDENCE)
public SecurityFilterChain authorizationServerSecurityFilterChain(HttpSecurity http) throws Exception {
OAuth2AuthorizationServerConfigurer authorizationServerConfigurer = new OAuth2AuthorizationServerConfigurer();
// 个性化认证授权端点
http.apply(authorizationServerConfigurer.tokenEndpoint((tokenEndpoint) -> {
// 注入自定义的授权认证Converter
tokenEndpoint.accessTokenRequestConverter(accessTokenRequestConverter())
// 登录成功处理器
.accessTokenResponseHandler(new PigAuthenticationSuccessEventHandler())
// 登录失败处理器
.errorResponseHandler(new PigAuthenticationFailureEventHandler());
// 个性化客户端认证
}).clientAuthentication(oAuth2ClientAuthenticationConfigurer ->
// 处理客户端认证异常
oAuth2ClientAuthenticationConfigurer.errorResponseHandler(new PigAuthenticationFailureEventHandler()))
// 授权码端点个性化confirm页面
.authorizationEndpoint(authorizationEndpoint -> authorizationEndpoint
.consentPage(SecurityConstants.CUSTOM_CONSENT_PAGE_URI)));
RequestMatcher endpointsMatcher = authorizationServerConfigurer.getEndpointsMatcher();
DefaultSecurityFilterChain securityFilterChain = http.requestMatcher(endpointsMatcher)
.authorizeRequests(authorizeRequests -> authorizeRequests.anyRequest().authenticated())
// redis存储token的实现
.apply(authorizationServerConfigurer.authorizationService(authorizationService)
//token端口配置
.authorizationServerSettings(AuthorizationServerSettings.builder()
.issuer(SecurityConstants.PROJECT_LICENSE).build()))
// 授权码登录的登录页个性化
.and().apply(new FormIdentityLoginConfigurer()).and().build();
// 注入自定义授权模式实现
addCustomOAuth2GrantAuthenticationProvider(http);
return securityFilterChain;
}
1.4.许可类型对比
1.4.1 密码模式默认不支持
Spring Authorization Server 是基于OAuth 2.1
目前支持的许可类型有(https://docs.spring.io/spring-authorization-server/docs/current/reference/html/overview.html)
可以看到默认不支持密码模式,当然它支持用户自定义许可类型。如pig项目自定义密码许可模式的扩展(下一章分析)
1.4.2 新增Opaque Token
我们看官网给的介绍,Opaque Token是怎样工作的。https://docs.spring.io/spring-security/reference/servlet/oauth2/resource-server/opaque-token.html
2.总结
正如chatGPT所言,Spring Authorization Server 相比Spring Security Oauth2更加简单和标准化。整个授权过程也清晰很多。
扩展和实现。

原文始发于微信公众号(小李的源码图):拥抱Spring全新OAuth解决方案(一)
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/145289.html