说明
SpringSecurity接入Oauth2认证有两种方式,一种是SpringCloud推荐的依赖org.springframework.cloud:spring-cloud-starter-oauth2+org.springframework.cloud:spring-cloud-starter-security,另一种是不依赖SpringCloud的org.springframework.security:spring-security-oauth2-client
目前主要想实现一套单点登录的统一逻辑,也没有依赖到SpringCloud,因此采用第二种实现org.springframework.security:spring-security-oauth2-client
需要注意的是,Oauth2原来还有org.springframework.security.oauth.boot:spring-security-oauth2-autoconfigure和org.springframework.security.oauth:spring-security-oauth2这两个是历史版本的,已经废弃了
依赖
本次主要依赖SpringSecurity 5.3的版本,因为自己项目springboot版本问题,建议依赖5.7版本,这个更新,当然,相关的配置肯定会有稍许调整
1 2 3 4 5 6 7 8 9
| <dependency> <groupId>org.springframework.security</groupId> <artifactId>spring-security-oauth2-client</artifactId> <version>5.3.3.RELEASE</version> </dependency> <dependency> <groupId>com.kewen.framework.auth</groupId> <artifactId>auth-spring-boot-starter</artifactId> </dependency>
|
Java配置
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93
| @Configuration @EnableConfigurationProperties(Oauth2Properties.class) public class Oauth2Config extends WebSecurityConfigurerAdapter {
@Autowired private SecurityAuthenticationSuccessHandler successHandler;
@Autowired private SecurityAuthenticationExceptionResolverHandler exceptionResolverHandler;
@Autowired private Oauth2Properties oauth2Properties;
@Bean public AuthorizationRequestRepository<OAuth2AuthorizationRequest> authorizationRequestRepository() { return new HttpSessionOAuth2AuthorizationRequestRepository(); } @Bean public Oauth2AuthenticationSuccessResultConverter oauth2JsonSuccessResultConverter(){ return new Oauth2AuthenticationSuccessResultConverter(); } @Bean public OAuth2AccessTokenResponseClient<OAuth2AuthorizationCodeGrantRequest> accessTokenResponseClient() { return new DefaultAuthorizationCodeTokenResponseClient(); }
@Bean public OAuth2UserService oAuth2UserService() { DefaultOAuth2UserService defaultOAuth2UserService = new DefaultOAuth2UserService(); defaultOAuth2UserService.setRestOperations(new RestOperationBuilder().enableSsl(false).build()); return defaultOAuth2UserService; }
@Override protected void configure(HttpSecurity http) throws Exception { ClientRegistrationRepository clientRegistrationRepository = clientRegistrationRepository(); http.oauth2Login(oauth2 -> { oauth2 .successHandler(successHandler) .failureHandler(exceptionResolverHandler) .authorizationEndpoint(endpoint -> { endpoint.baseUri(oauth2Properties.getAuthorizationUri()) ; }) .tokenEndpoint(endpoint -> { endpoint.accessTokenResponseClient(accessTokenResponseClient()); }) .userInfoEndpoint(endpoint -> { endpoint.userService(oAuth2UserService()); }) .loginProcessingUrl(oauth2Properties.getLoginProcessingUrl()) .clientRegistrationRepository(clientRegistrationRepository) ; }); } private ClientRegistrationRepository clientRegistrationRepository(){ List<ClientRegistration> registrationList = getClientRegistrations(); return new InMemoryClientRegistrationRepository(registrationList); }
private List<ClientRegistration> getClientRegistrations() { List<ClientRegistration> registrationList = oauth2Properties.getClients().stream().map( client -> { ClientRegistration.Builder builder = ClientRegistration.withRegistrationId(client.getRegistrationId()); return builder.registrationId(client.getRegistrationId()).clientId(client.getClientId()) .clientSecret(client.getClientSecret()) .clientAuthenticationMethod(ClientAuthenticationMethod.BASIC) .authorizationGrantType(AuthorizationGrantType.AUTHORIZATION_CODE) .redirectUriTemplate("{baseUrl}/login/oauth2/code/{registrationId}") .authorizationUri(client.getAuthorizationUri()) .userInfoUri(client.getUserInfoUri()) .userNameAttributeName(client.getUserNameAttributeName()) .scope(client.getScopes()) .tokenUri(client.getTokenUri()) .build(); } ).collect(Collectors.toList()); return registrationList; } }
|
主要配置在configure方法中,最小需要配置授权端点.authorizationEndpoint(),令牌端点.tokenEndpoint(),用户信息端点.userInfoEndpoint(),client存储的相关信息.clientRegistrationRepository()否则无法启动;
涉及到的登录端点有两个
- 默认的sp登录发起地址
/oauth2/authorize
- IDP授权码回调的地址
{baseUrl}/login/oauth2/code/{registrationId}
这两个地址按需修改,同样,可以根据模板来自定义回调地址
注意
这里需要注意的是这里Oauth2认证完成之后,在OAuth2LoginAuthenticationFilter中会直接构造一个OAuth2AuthenticationToken并返回,导致后续添加到Session中的对象只能是OAuth2AuthenticationToken,这个即使换了AuthticationProvider也没有办法处理,除非自定义Filter修改代码,但这又是SpringSecurity不推荐的,会破坏其共享对象的结构,导致后续出现一系列问题,如sesison配置问题,rememberme配置问题等
后续版本不知道SpringSecurity会留出这个扩展没有。