Spring Security OAuth2:如何为两类用户提供两个单独的登录链接?
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Spring Security OAuth2:如何为两类用户提供两个单独的登录链接?相关的知识,希望对你有一定的参考价值。
我正在创建一个Web应用程序,它有两种类型的用户,比如A和B.目前,登录流程是这样的,
index.html
上有一个登录链接,指向/login
- 用户被重定向到谷歌登录页面,用户登录并重定向到
index.html
- 此时,我必须验证用户是否经过身份验证,如果是,用户的类型(A,B或新用户)是什么,则进一步的过程是将它们重定向到适当的链接。
根据两个表中是否存在条目来确定用户的类型,一个用于A,一个用于B.
代码看起来像这样,
@EnableOAuth2Sso
@Configuration
public class WebSecurityConfigurator extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.csrf()
.disable()
.antMatcher("/**")
.authorizeRequests()
.antMatchers("/", "/index.html")
.permitAll()
.anyRequest()
.authenticated();
}
}
我想简化这个过程,其中,
- 有两个登录链接,比如
/login-A
和/login-B
- 用户点击其中一个,重定向到Google,进行身份验证,然后重定向到相应的页面。
如果使用@EnableOAuth2Client
代替@EnableOAuth2Sso
,您将能够定义多个OAuth2ClientAuthenticationProcessingFilter。
你的配置会像..
@EnableOAuth2Client
@RestController
@Configuration
public class WebSecurityConfigurator extends WebSecurityConfigurerAdapter {
@Autowired
OAuth2ClientContext oauth2ClientContext;
@RequestMapping("/user")
public Principal user(Principal principal) {
return principal;
}
// @formatter:off
@Override
protected void configure(HttpSecurity http) throws Exception {
http.antMatcher("/**")
.addFilterBefore(ssoFilter(), BasicAuthenticationFilter.class)
.authorizeRequests()
.antMatchers("/", "/login**", "/webjars/**")
.permitAll()
.anyRequest()
.authenticated()
.and()
.logout()
.logoutSuccessUrl("/").permitAll().and().csrf()
.csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse());
}
// @formatter:on
private Filter ssoFilter() {
CompositeFilter filter = new CompositeFilter();
List filters = new ArrayList<>();
OAuth2ClientAuthenticationProcessingFilter googleFilterA = new OAuth2ClientAuthenticationProcessingFilter(
"/login/googleA");
OAuth2RestTemplate googleTemplateA = new OAuth2RestTemplate(googleA(), oauth2ClientContext);
googleFilterA.setRestTemplate(googleTemplateA);
tokenServices = new UserInfoTokenServices(googleResource().getUserInfoUri(), googleA().getClientId());
tokenServices.setRestTemplate(googleTemplateA);
googleFilterA.setTokenServices(tokenServices);
OAuth2ClientAuthenticationProcessingFilter googleFilterB = new OAuth2ClientAuthenticationProcessingFilter(
"/login/googleB");
OAuth2RestTemplate googleTemplateB = new OAuth2RestTemplate(googleB(), oauth2ClientContext);
googleFilterB.setRestTemplate(googleTemplateB);
tokenServices = new UserInfoTokenServices(googleResource().getUserInfoUri(), googleB().getClientId());
tokenServices.setRestTemplate(googleTemplateB);
googleFilterB.setTokenServices(tokenServices);
filters.add(googleFilterA);
filters.add(googleFilterB);
filter.setFilters(filters);
return filter;
}
@Bean
public FilterRegistrationBean oauth2ClientFilterRegistration(OAuth2ClientContextFilter filter) {
FilterRegistrationBean registration = new FilterRegistrationBean();
registration.setFilter(filter);
registration.setOrder(-100);
return registration;
}
@Bean
@ConfigurationProperties("google.clientA")
public AuthorizationCodeResourceDetails googleA() {
return new AuthorizationCodeResourceDetails();
}
@Bean
@ConfigurationProperties("google.resource")
public ResourceServerProperties googleResource() {
return new ResourceServerProperties();
}
@Bean
@ConfigurationProperties("google.clientB")
public AuthorizationCodeResourceDetails googleB() {
return new AuthorizationCodeResourceDetails();
}
}
您将在application.yml文件中定义以下属性
google:
clientA:
clientId: 12894100090-tqso3lih5o42isneort886la2pesafmp.apps.googleusercontent.com
clientSecret: 9xfU16efvxQ-BTMsXT9wOLpw
accessTokenUri: https://accounts.google.com/o/oauth2/token
userAuthorizationUri: https://accounts.google.com/o/oauth2/auth
clientAuthenticationScheme: form
scope: profile email
redirect-uri: http://yourapp.com/pathA
clientB:
clientId: 12894100090-tqso3lih5o42isneort886la2pesafmp.apps.googleusercontent.com
clientSecret: 9xfU16efvxQ-BTMsXT9wOLpw
accessTokenUri: https://accounts.google.com/o/oauth2/token
userAuthorizationUri: https://accounts.google.com/o/oauth2/auth
clientAuthenticationScheme: form
scope: profile email drive
redirect-uri: http://yourapp.com/pathB
resource:
userInfoUri: https://www.googleapis.com/oauth2/v3/userinfo
您的index.html将为两种类型的用户提供两个链接/login/googleA
和/login/googleB
。
有关详细信息,请参阅以下教程。
https://spring.io/guides/tutorials/spring-boot-oauth2/
更新 -
要重定向到不同的页面,您可以为两个客户端扩展OAuth2ClientAuthenticationProcessingFilter
类,例如..
class GoogleAAuthenticationProcessingFilter extends OAuth2ClientAuthenticationProcessingFilter {
@Override
protected void successfulAuthentication(HttpServletRequest request, HttpServletResponse response,
FilterChain chain, Authentication authResult) throws IOException, ServletException {
super.successfulAuthentication(request, response, chain, authResult);
// here you can redirect to whatever location you want to
}
}
class GoogleBAuthenticationProcessingFilter extends OAuth2ClientAuthenticationProcessingFilter {
@Override
protected void successfulAuthentication(HttpServletRequest request, HttpServletResponse response,
FilterChain chain, Authentication authResult) throws IOException, ServletException {
super.successfulAuthentication(request, response, chain, authResult);
// here you can redirect to whatever location you want to
}
}
并使用扩展类
OAuth2ClientAuthenticationProcessingFilter googleFilterA = new GoogleAAuthenticationProcessingFilter(
"/login/googleA");
OAuth2ClientAuthenticationProcessingFilter googleFilterB = new GoogleBAuthenticationProcessingFilter(
"/login/googleB");
基本上它是可能的,但与单个@EnableOAuth2Sso
注释相比需要更多的配置工作。当使用此注释时,它应用SsoSecurityConfigurer
,它将OAuth2ClientAuthenticationProcessingFilter
(默认情况下为OAuth2SsoProperties
)的登录页面路径注册为给定模式(在您的情况下为/login
)中的专用/**
。然而,not possible在同一个应用程序中有多个@EnableOAuth2Sso
和OAuth2SsoProperties
类。因此,您需要为每种类型的用户手动注册多个WebSecurityConfigurerAdapter
和相应的OAuth2ClientAuthenticationProcessingFilter
以及不同的登录页面/模式/授权逻辑。
1 - 配置Spring Security配置文件 2 - 编写自定义身份验证成功处理程序类
<user name="userA" password="userApass" authorities="ROLE_A" />
<user name="userB" password="userBpass" authorities="ROLE_B" />
protected String determineTargetUrl(Authentication authentication) {
boolean isUserA = false;
boolean isUserB= false;
Collection<? extends GrantedAuthority> authorities
= authentication.getAuthorities();
for (GrantedAuthority grantedAuthority : authorities) {
if (grantedAuthority.getAuthority().equals("ROLE_A")) {
isUserA = true;
break;
} else if (grantedAuthority.getAuthority().equals("ROLE_B")) {
isUserB = true;
break;
}
}
if (isUserA) {
return "/pageA.html";
} else if (isUserB) {
return "/pageB.html";
} else {
throw new IllegalStateException();
}
}
以上是关于Spring Security OAuth2:如何为两类用户提供两个单独的登录链接?的主要内容,如果未能解决你的问题,请参考以下文章
如何将 spring security 与 rest oauth2 服务和 spring social 集成?
如何使用 Spring Cloud Security 实现 OAuth2“令牌交换”
如何在 Spring Security 中动态指定 OAuth2 资源详细信息?
如何在 grails 和现有 oauth2 提供程序中使用 Spring Security 实现基于表单的登录
如何使用 spring-social-security SocialAuthenticationFilter 指定 OAuth2 范围?