Spring Security OAuth2:如何为两类用户提供两个单独的登录链接?

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Spring Security OAuth2:如何为两类用户提供两个单独的登录链接?相关的知识,希望对你有一定的参考价值。

我正在创建一个Web应用程序,它有两种类型的用户,比如A和B.目前,登录流程是这样的,

  1. index.html上有一个登录链接,指向/login
  2. 用户被重定向到谷歌登录页面,用户登录并重定向到index.html
  3. 此时,我必须验证用户是否经过身份验证,如果是,用户的类型(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();
    }
}

我想简化这个过程,其中,

  1. 有两个登录链接,比如/login-A/login-B
  2. 用户点击其中一个,重定向到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/

http://www.littlebigextra.com/spring-boot-oauth2-tutorial-for-authorizing-through-facebook-google-linkedin-and-twitter/

更新 -

要重定向到不同的页面,您可以为两个客户端扩展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在同一个应用程序中有多个@EnableOAuth2SsoOAuth2SsoProperties类。因此,您需要为每种类型的用户手动注册多个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 范围?

如何在我的 Spring Boot Security OAuth2 应用程序中仅为某些类启用 OAuth2?