简体   繁体   中英

Spring security Oauth 2 with ajax login and form login

Developing an application which requires REST authentication as well as form login. Currently spring security oauth 2 with ajax login works. In subsequent request could send 'Authorization Bearer ' and server successfully authorizes the request.

Ajax code for login/signin

function signIn() {
            $.ajax({
            type : 'POST',
            url : 'oauth/token',
            data : {
                'client_id' : 'XXXXX',
                'client_secret' : 'YYYYYY',
                'grant_type' : 'password',
                'username' :encodeURIComponent($('#login').val()),
                'password' : encodeURIComponent($('#password').val()),
                'scope' : 'read write'
            },
             beforeSend: function(xhr) {
                 xhr.setRequestHeader("Authorization", "Basic " + $.base64.encode("XXXXX" + ':' + "YYYYYY") )
               },
            success : function(response) {
                 var expiredAt = new Date();
                    expiredAt.setSeconds(expiredAt.getSeconds() + response.expires_in);
                    response.expires_at = expiredAt.getTime();
                    localStorage.setItem('ls.token', JSON.stringify(response));
                    $.cookie("Authorization", "Bearer " + JSON.parse(localStorage.getItem("ls.token")).access_token );
                    var link = /*[[@{/}]]*/;
                    $(location).attr('href',link);
            }
        });
    }

In subsequent AJAX requests authorization is included as

  $.ajax({
       url: 'api/ZZZZZ/',
       type: 'GET',
     beforeSend: function(xhr) {
       xhr.setRequestHeader("Authorization", "Bearer " + JSON.parse(localStorage.getItem("ls.token")).access_token )
     },
       success: function(data) {}

I could see the authorization bearer in request header while making AJAX call

 Accept */*
 Accept-Encoding    gzip, deflate
 Accept-Language    en-US,en;q=0.5
 Authorization  Bearer 49ef5d34-88a2-4e20-bd7a-87042c6a62b4
 Cache-Control  max-age=0
 Connection keep-alive
 Host   localhost:8080
 Referer    http://localhost:8080/productview?productId=19
 User-Agent Mozilla/5.0 (Macintosh; Intel Mac OS X 10.11; rv:42.0)      Gecko/20100101 Firefox/42.0
 X-Requested-With   XMLHttpRequest

My spring security configuration looks like

  package com.geekyworks.equip.wowperks.config;

  import javax.inject.Inject;

  import org.springframework.context.annotation.Bean;
  import org.springframework.context.annotation.Configuration;
  import org.springframework.core.annotation.Order;
  import org.springframework.security.authentication.AuthenticationManager;
  import   org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
  import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
  import org.springframework.security.config.annotation.web.builders.HttpSecurity;
  import org.springframework.security.config.annotation.web.builders.WebSecurity;
  import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
  import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
  import org.springframework.security.core.userdetails.UserDetailsService;
  import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
  import org.springframework.security.crypto.password.PasswordEncoder;
  import org.springframework.security.data.repository.query.SecurityEvaluationContextExtension;

  @Configuration
  @EnableWebSecurity
  @EnableGlobalMethodSecurity(prePostEnabled = true, securedEnabled = true)
  public class SecurityConfiguration extends WebSecurityConfigurerAdapter {

 @Inject
 private UserDetailsService userDetailsService;

@Bean
public PasswordEncoder passwordEncoder() {
    return new BCryptPasswordEncoder();
}

@Inject
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
    auth
        .userDetailsService(userDetailsService)
            .passwordEncoder(passwordEncoder());
}

@Override
public void configure(WebSecurity web) throws Exception {
    web.ignoring()
        .antMatchers("/scripts/**/*.{js,html}")
        .antMatchers("/bower_components/**")
        .antMatchers("/i18n/**")
        .antMatchers("/assets/**")
        .antMatchers("/swagger-ui/index.html")
        .antMatchers("/api/register")
        .antMatchers("/api/activate")
        .antMatchers("/api/account/reset_password/init")
        .antMatchers("/api/account/reset_password/finish")
        .antMatchers("/api/home/**")
        .antMatchers("/api/product/**")
        .antMatchers("/test/**")
        .antMatchers("/devadmin/**")
        .antMatchers("/signin")
        .antMatchers("/static/api-guide.html");
}


@Order(67) // LOWEST
@Configuration
public static class NoAuthConfigurationAdapter extends WebSecurityConfigurerAdapter {
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
        .antMatcher("/**")
        .authorizeRequests()
        .anyRequest()
        .permitAll();
    }
}

@Override
@Bean
public AuthenticationManager authenticationManagerBean() throws Exception {
    return super.authenticationManagerBean();
}

@Bean
public SecurityEvaluationContextExtension securityEvaluationContextExtension() {
    return new SecurityEvaluationContextExtension();
}

}

For all normal http request I'm always getting the spring user as 'anonymousUser' even after login.

Normal http request header (non AJAX) does not include Authorization bearer in request header

      Accept    text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
      Accept-Encoding   gzip, deflate
      Accept-Language   en-US,en;q=0.5
      Cache-Control max-age=0
      Connection    keep-alive
      Cookie    Authorization=Bearer%2049ef5d34-88a2-4e20-bd7a-87042c6a62b4
      Host  localhost:8080
      Referer   http://localhost:8080/
      User-Agent    Mozilla/5.0 (Macintosh; Intel Mac OS X 10.11; rv:42.0) Gecko/20100101 Firefox/42.0

Instead it contains authorization bearer as Cookie information. I added cookie information post AJAX login.

Any idea how can I make FORM and AJAX authentication to work simultaneously using spring security oauth in single application?

The way spring security manages form based authentication is totaly different what you are trying to achive through oauth2.0. When you are using ajax (oauth2.0) way of authenticating (which is actualy authorization process of client application by user with username and password) user, only your client application (application through which you are firing ajax request) will get authenticated through spring security filter and SecurityContextHolder will have authentication object of authenticated client application not the user. If you will see your security configuration you are allowing all the request to pass without authentication in case of non ajax login. To enable form based login you need to configure your security to protect all other url except login url... something as given below

@Override
    protected void configure(HttpSecurity http) throws Exception {
        http.csrf().disable().authorizeRequests()
                .antMatchers("/**")
                .authenticated().and().formLogin();
    }

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM