Java SpringSecurityOAuth2:如何为两种类型的用户提供两个独立的登录链接?

Java SpringSecurityOAuth2:如何为两种类型的用户提供两个独立的登录链接?,java,spring-boot,login,oauth-2.0,Java,Spring Boot,Login,Oauth 2.0,我正在创建一个web应用程序,它有两种类型的用户,比如a和B。目前,登录流是这样的 @EnableOAuth2Sso @Configuration public class WebSecurityConfigurator extends WebSecurityConfigurerAdapter { @Override protected void configure(HttpSecurity http) throws Exception { http

我正在创建一个web应用程序,它有两种类型的用户,比如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();
    }
}
  • index.html
    上有一个登录链接,指向
    /login
  • 用户被重定向到google登录页面,在该页面中,用户登录并被重定向到
    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,进行身份验证,并重定向到相应的页面

  • 基本上这是可能的,但与单个
    @enableAuth2sso
    注释相比,需要更多的配置工作。使用此注释时,它将应用
    SSOSecurityConfigure
    ,该配置程序将专用的
    OAuth2ClientAuthenticationProcessingFilter
    注册为给定模式(
    /**
    在您的情况下)的登录页面路径,该路径来自
    OAuth2ssProperties
    /login
    )。但是,在同一应用程序中必须有多个
    @enableAuth2sso
    OAuth2ssoProperty
    类。因此,您需要手动注册多个
    websecurityConfigureAdapter
    ,并为每种类型的用户注册相应的
    OAuth2ClientAuthenticationProcessingFilter
    ,使用不同的登录页面/模式/授权逻辑。

    1-配置Spring安全配置文件
    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();
            }
        }
    
    
    受保护的字符串determinateTargetURL(身份验证){
    布尔值isUserA=false;
    布尔值isUserB=false;
    
    集合如果使用
    @enableouth2client
    代替
    @enableouth2sso
    ,则可以定义多个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();
     }
     }
    
    对于这两种类型的用户,index.html将有两个链接
    /login/googleA
    /login/googleB

    有关更多详细信息,请参阅以下教程

    更新-

    要重定向到不同的页面,您可以为以下两个客户端扩展
    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");
    

    在登录之前,您如何知道用户类型(A或B)?您不需要他们先登录吗?您当前的流程很有意义。另外,您的流程如何简化为两个链接而不是一个链接?@KeatsPeeks让我们假设我有猫和狗作为用户,所以猫会单击“以猫的身份登录”,狗会单击“以狗的身份登录”。这样,它将隐含用户类型。这样,我不需要在登录后询问用户。只需少一步,前端的逻辑也少一点。您可以尝试使用较低级别的注释“@EnableOAuth2Client”代替“@EnableOAuth2SO”。但它需要更多的代码。请参阅本教程-我已经更新了我的答案le重定向到不同的页面。除了重定向部分外,它是有效的。这两个链接始终重定向到homepage(/)@Registered User-我已更新我的答案以处理重定向到不同页面的问题。