Перенаправление единого входа не работает с Spring Security Oauth

#spring-boot #authentication #spring-security #single-sign-on #spring-security-oauth2

Вопрос:

Я создаю проект с spring security для входа в систему с помощью единого входа Oauth, это часть моего проекта, использующая Spring Security 5, jQuery для вызова ajax, spring-security-oauth2 и spring-security-oauth2-автоконфигурация для авторизации и сервера ресурсов в одном проекте Spring Boot 2, я хочу использовать пользовательскую страницу входа и единый вход для многих клиентов. Я поискал вокруг, но я закончил с пользовательской страницей входа, достигнутой с помощью uri:http://localhost:8080/oauth/authorize?grant_type=authorization_codeamp;response_type=codeamp;client_id=SampleClientIdamp;state=1234 но после вставки учетных данных для входа приложение не перенаправляется на клиент Oauth, и сеанс не является общим, и оно всегда будет запрашивать вход,

это мой класс конфигурации безопасности

 @Configuration
@Order(1)
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
    
       private static final String PROD = "prod";
        
        private static final RequestMatcher PUBLIC_URLS = new OrRequestMatcher(
                new AntPathRequestMatcher("/error"),
                new AntPathRequestMatcher("/register/v1"),            
                // -- dash
                new AntPathRequestMatcher("/html/*.html"), 
                new AntPathRequestMatcher("/css/**"), 
                new AntPathRequestMatcher("/js/**"), 
                new AntPathRequestMatcher("/favicon.ico"), 
                new AntPathRequestMatcher("/*.html"), 
                
                new AntPathRequestMatcher("/login/v1"),
                new AntPathRequestMatcher("/resetPassword/v1"),
                new AntPathRequestMatcher("/resetPasswordOk"),
                new AntPathRequestMatcher("/changePassword/**"),
                new AntPathRequestMatcher("/updatePassword/**"),
                new AntPathRequestMatcher("/savePassword/**"),
                new AntPathRequestMatcher("/config"),
                new AntPathRequestMatcher("/auth/**"),
                new AntPathRequestMatcher("/oauth/authorize"),
                new AntPathRequestMatcher("/oauth/token")
        );
        
        
        private static final RequestMatcher PUBLIC_URLS_TEST = new OrRequestMatcher(
                new AntPathRequestMatcher("/error"),
                new AntPathRequestMatcher("/register/v1"),
                // -- swagger ui
                new AntPathRequestMatcher("/swagger-resources/**"),  
                //new AntPathRequestMatcher("/swagger-ui.html"),
                new AntPathRequestMatcher("/swagger.html"),  
                new AntPathRequestMatcher("/v2/api-docs"),  
                new AntPathRequestMatcher("/webjars/**"), 
                
                // -- dash
                new AntPathRequestMatcher("/html/*.html"), 
                new AntPathRequestMatcher("/css/**"), 
                new AntPathRequestMatcher("/js/**"), 
                new AntPathRequestMatcher("/favicon.ico"), 
                new AntPathRequestMatcher("/*.html"), 
                
                new AntPathRequestMatcher("/login/v1"),
                new AntPathRequestMatcher("/resetPassword/v1"),
                new AntPathRequestMatcher("/resetPasswordOk"),
                new AntPathRequestMatcher("/changePassword/**"),
                new AntPathRequestMatcher("/updatePassword/**"),
                new AntPathRequestMatcher("/savePassword/**"),
                new AntPathRequestMatcher("/config"),
                new AntPathRequestMatcher("/auth**"),
                new AntPathRequestMatcher("/oauth/authorize"),
                new AntPathRequestMatcher("/oauth/token")
        ); 
        private static final RequestMatcher PROTECTED_URLS = new NegatedRequestMatcher(PUBLIC_URLS);
        
        @Autowired
        private TokenAuthenticationProvider authenticationProvider; 
     
        @Override
        protected void configure(AuthenticationManagerBuilder auth) throws Exception{
             auth.authenticationProvider(authenticationProvider);
        }
        
        @Override
        public void configure(WebSecurity web) {
            if (config.getEnv().equalsIgnoreCase(PROD)) {
                web.ignoring().requestMatchers(PUBLIC_URLS);
            }else {
                web.ignoring().requestMatchers(PUBLIC_URLS_TEST);
            }
        }

        @Override
        protected void configure(HttpSecurity http) throws Exception {
            http
                .sessionManagement().sessionCreationPolicy(STATELESS)
                    .and()
                .exceptionHandling().accessDeniedHandler(accessDeniedHandler())
                .defaultAuthenticationEntryPointFor(forbiddenEntryPoint(), PROTECTED_URLS)
                    .and()
                .authenticationProvider(authenticationProvider)
                .addFilterBefore(restAuthenticationFilter(), AnonymousAuthenticationFilter.class)
                .authorizeRequests()
                .anyRequest().authenticated()
                    .and()
                .formLogin()
                    .loginPage("/login.html")
                    .usernameParameter("username")
                    .passwordParameter("password")
                    .loginProcessingUrl("/login/v1")
                    .failureUrl("/login.html?error=true")
                    .and()
                    .logout()
                    .logoutUrl("/logout")
                    .deleteCookies("JSESSIONID")
                    .and()
                    .csrf().disable()
                ;          
       
        }
       


        @Bean
        TokenAuthenticationFilter restAuthenticationFilter() throws Exception {
            TokenAuthenticationFilter filter = new TokenAuthenticationFilter(PROTECTED_URLS);
            filter.setAuthenticationManager(authenticationManager());
            filter.setAuthenticationFailureHandler(failureHandler());
            return filter;
        }

        private AuthenticationFailureHandler failureHandler() {
            return new CustomAuthenticationFailureHandler();
        }

        
        private AccessDeniedHandler accessDeniedHandler() {
            return new CustomAccessDeniedHandler();
        }
       
        @Bean
        FilterRegistrationBean<TokenAuthenticationFilter> disableAutoRegistration(TokenAuthenticationFilter filter) {
            FilterRegistrationBean<TokenAuthenticationFilter> registration = new FilterRegistrationBean<TokenAuthenticationFilter>(filter);
            registration.setEnabled(false);
            return registration;
        }

        @Bean
        AuthenticationEntryPoint forbiddenEntryPoint() {
            return new HttpStatusEntryPoint(FORBIDDEN);
        }
        
        @Bean
        public CustomPasswordEncoder passwordEncoder() {
            return new CustomPasswordEncoder();
        }
    }
 

это мой класс конфигурации сервера авторизации:

 @Configuration
@EnableAuthorizationServer
public class OAuth2Config extends AuthorizationServerConfigurerAdapter {
    
    @Override
    public void configure(ClientDetailsServiceConfigurer clients) throws Exception{
        clients.inMemory()
                .withClient("SampleClientId")
                .secret(passwordEncoder3.encode("secret"))
                .scopes("resource:read")
                .authorizedGrantTypes("authorization_code")
                .redirectUris("http://localhost:8082/app1")
                //.redirectUris("http://localhost:8081/oauth/login/client-app");
                .autoApprove(true);
    }

    private final PasswordEncoder passwordEncoder3;

    public OAuth2Config(PasswordEncoder passwordEncoder) {
        this.passwordEncoder3 = passwordEncoder;
    }
    
    @Override
    public void configure(
        AuthorizationServerSecurityConfigurer oauthServer) throws Exception {
        oauthServer.tokenKeyAccess("permitAll()")
            .checkTokenAccess("isAuthenticated()");
    }    
}
 

this is my Spring Boot app class:

 @EnableResourceServer
@SpringBootApplication
public class Application{

    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }
    
    @Bean
    public MessageSource messageSource() {
        ReloadableResourceBundleMessageSource messageSource  = new ReloadableResourceBundleMessageSource();
        messageSource.setBasename("classpath:messages");
        messageSource.setDefaultEncoding("UTF-8");
        return messageSource;
    }
    
    @Bean
    public LocalValidatorFactoryBean getValidator() {
        LocalValidatorFactoryBean bean = new LocalValidatorFactoryBean();
        bean.setValidationMessageSource(messageSource());
        return bean;
    }
}
 

this is my custom login page that I’ve created:

 <body>
    <div class="form-signin">
        <form th:action="@{/login/v1}" method="post" style="max-width: 350px; margin: 0 auto;">
            <!--<div th:if="${param.error}" class="alert alert-error">Invalid username and password.</div>
                <div th:if="${param.logout}" class="alert alert-success">You have been logged out.</div>-->

            <div class="form-label-group" id="username-group">
                <input id="username" name="username" class="form-control" placeholder="Username" required autofocus> <label for="username">Utente</label>
            </div>

            <div class="form-label-group" id="password-group">
                <input type="password" id="password" name="password" class="form-control" placeholder="Password" required> <label for="password">Password</label>
            </div>

            <p id="label-login-action"></p>
            <button class="btn btn-lg btn-secondary btn-block" type="submit" id="login">Login</button>
            <p class="mt-5 mb-3 text-muted text-center">amp;copy; 2016-2020</p>
        </form>
    </div>

    <script>
      $(document).ready(function () {
        
        Cookies.remove("token");
        
        $("#login").on("click", function(){
            login($("#username").val(),$("#password").val(), $("#tfauth").val());
        });
        
        $("#password").on("keydown", function(e){
            if (e.which == 13) {
                $("#login").click();
            }
        })
    }); 
    </script>
 

это мой вызов jquery с ajax

 var login = function(username, password, code) {
    
    var loginLabel = $("#label-login-action");

    loginLabel.removeClass("alert-danger");
    loginLabel.addClass("alert alert-warning");
    loginLabel.html("Logging...");
    var endpoint = config.path   "/login/v1";
    $.postJSON2(endpoint, {
        username : username,
        password : password,
        code : code
    }, function(response) {
        if (response.token) {       
            Cookies.remove('lastError');
            Cookies.set('token', response.token);
            goToPage("index");
    }, function(request, status, error) {});
}
 

и контроллер REST для входа в систему

     @PostMapping(path = "/login", consumes = "application/json", produces = "application/json")
    public UserLoginResponse login(@Valid @RequestBody UserLoginRequest user, BindingResult bindingResult,  
            HttpServletRequest request, HttpServletResponse response, Locale locale) throws Exception {

...

}

 

Комментарии:

1. Похоже, вы используете устаревший spring-security-oauth проект. Пожалуйста, вместо этого используйте поддержку OAuth 2.0, предоставляемую Spring Security .