我正在创建一个Web应用程序,它有两种类型的用户,比如A和B.目前,登录流程是这样的,
index.html
上有一个登录链接,指向/login
index.html
根据两个表中是否存在条目来确定用户的类型,一个用于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
如果使用@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();
}
}