Spring安全类工作在不同的端口尝试使用来自apk的有效凭据登录,得到“**anonymousUser**”

Posted

技术标签:

【中文标题】Spring安全类工作在不同的端口尝试使用来自apk的有效凭据登录,得到“**anonymousUser**”【英文标题】:Spring security class working In different port try to login with valid credentials from apk ,got "**anonymousUser**" 【发布时间】:2017-01-13 21:49:45 【问题描述】:

我的服务器端代码在 8080 端口工作,该端口实现了弹簧安全性,我试图从 8100 .apk(离子浏览器视图)中访问它。在我的登录控制器中,我成功获得了 anonymousUser 部分。

我的服务器端loggedInSuccess方法代码是,

Authentication auth = SecurityContextHolder.getContext().getAuthentication();

我在身份验证参考中得到了以下内容 (auth) org.springframework.security.authentication.AnonymousAuthenticationToken@9055c2bc: Principal: anonymousUser; Credentials: [PROTECTED]; Authenticated: true; Details: org.springframework.security.web.authentication.WebAuthenticationDetails@b364: RemoteIpAddress: 0:0:0:0:0:0:0:1; SessionId: null; Granted Authorities: ROLE_ANONYMOUS

然后我加了getPrinciple()

Object principal = SecurityContextHolder.getContext().getAuthentication().getPrincipal();

principal ref 我只有一个字符串anonymousUser

如果相同的代码在像Spring boot project这样的桌面版本中完美运行。问题只出现在离子到服务器端代码访问时间。用户名和密码是正确的,但我得到的是anonymousUser。下面我发布了我的java秒配置代码。

安全 Java 配置

  @Configuration
@EnableAspectJAutoProxy(proxyTargetClass = true)
@EnableGlobalMethodSecurity(prePostEnabled=true)
public class WebSecurityConfig extends WebSecurityConfigurerAdapter 

    @Autowired
    DataSource dataSource;

    @Autowired
    private SecurityUserService userDetailsService;

    @Override
    public void configure(WebSecurity web) throws Exception 
        web.ignoring().antMatchers("/user/createsocialuser");
    

    @Override
    public void configure(AuthenticationManagerBuilder auth) throws Exception 
        auth.userDetailsService(userDetailsService);
    


    @Override
    protected void configure(HttpSecurity http) throws Exception 
        ExceptionMappingAuthenticationFailureHandler loginFailureHandler = new ExceptionMappingAuthenticationFailureHandler();

        loginFailureHandler.setDefaultFailureUrl("/login/loginFailure");

        http
        .csrf().disable()
        .authorizeRequests()
        .regexMatchers("/admin.*").hasRole("ADMIN")
        .regexMatchers("/user.*").hasRole("USER")
            .and()
            .formLogin()
            .usernameParameter("j_username") 
            .passwordParameter("j_password")
            .loginProcessingUrl("/j_spring_security_check")
            .defaultSuccessUrl("/login/loginSuccess")
            .permitAll()
            .failureHandler(loginFailureHandler)
            .permitAll().and().logout().permitAll()
            .and().exceptionHandling()
            .accessDeniedPage("/accessDenied/403");
    



CORS 过滤代码用于访问不同的端口 在我的 ma​​in()

@Bean
    public FilterRegistrationBean someFilterRegistration() 

        FilterRegistrationBean registration = new FilterRegistrationBean();
        registration.setFilter(simpleCORSFilter());
        registration.addUrlPatterns("/*");
        registration.setName("simpleCORSFilter");
        registration.setOrder(1);
        return registration;
     

    @Bean(name = "simpleCORSFilter")
    public Filter simpleCORSFilter() 
        return new SimpleCORSFilter();
    

SimpleCORSFilter 类

@Component
public class SimpleCORSFilter  implements Filter 

    public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException 
        HttpServletResponse response = (HttpServletResponse) res;
        response.setHeader("Access-Control-Allow-Origin", "http://localhost:8100");
        response.setHeader("Access-Control-Allow-Credentials", "true");
        response.setHeader("Access-Control-Allow-Methods", "GET,HEAD,OPTIONS,POST,PUT");
        response.setHeader("Access-Control-Allow-Headers", "Access-Control-Allow-Headers, Access-Control-Allow-Origin,Accept, X-Requested-With, Content-Type, Access-Control-Request-Method, Access-Control-Request-Headers");
        chain.doFilter(req, res);
    

    public void init(FilterConfig filterConfig) 

    public void destroy() 

终于登录控制器

 @RestController
    @RequestMapping("/login")
    public class LoginController 
                @RequestMapping(value="/loginSuccess",method = RequestMethod.GET)
        public  ResponseWrapper  create(Principal principle)   

            try 
                        ResponseWrapper wrap = new ResponseWrapper();
                Object principal = SecurityContextHolder.getContext().getAuthentication().getPrincipal();
                wrap.setResult(principal);
                wrap.setResponseSuccess("success");
                System.out.println("-------sucess********----------------");
                return wrap;
             catch (Exception e) 
                e.printStackTrace();
            
            return null;
        


        @RequestMapping(value="/loginFailure",method = RequestMethod.GET)
        public  ResponseWrapper  loginFailure( )   

            try 
                ResponseWrapper wrap = new ResponseWrapper();
                wrap.setResponseError("loginFailed");
                        return wrap;
             catch (Exception e) 
                e.printStackTrace();
            
            return null;
        

    

在 angular ui 中,当我从 apk(离子浏览器窗口)点击它时,我得到了这个作为服务器端的响应

$scope.doLogin = function(loginform,userDetails) 
            if (loginform.$valid) 
                           $http.post(RestURL.baseURL+'/j_spring_security_check?j_username='+self.login.email+'&j_password='+self.login.password)
             .success(function(data) 
                             if(data.responseError == "loginFailed")                    
                     $location.url('login');
                               
           if(data.responseSuccess == "success")
              if(data.result != null)
                  var serverData = data.result;
                  console.warn('Server data =>',angular.toJson(serverData));
// I got it like Server data => "responseError":null,"responseDenied":null,"responseSuccess":"success","result":"anonymousUser"
                  $rootScope.userData= serverData;
                  $location.url('/home');
              
           
           ).error(function(data)          
            //callback 
            console.log('Error Some Internal server Error',data);
           );
              else 
              $log.log("form is invalid!");
              if (self.isNewUser) 
               loginform["username"].$dirty = true;
               loginform["usrtel"].$dirty = true;
               
              loginform["email"].$dirty = true;
              loginform["password"].$dirty = true;
             
            ;

登录html代码

<div class="row">
    <div class="col-md-8 form">
      <h1 class="title lead">Sign In</h1>
      <form class="form-horizontal" name="loginform" data-ng-submit="doLogin(loginform,userDetails)">
          <label for="username">Username:</label>
          <input type="text" class="form-control" ng-model="$parent.login.email" id="j_username" placeholder="Enter username" name="j_username" >
          <label for="password">Password:</label>
          <input type="password" class="form-control" ng-model="$parent.login.password" id="j_password" placeholder="Enter password" type="password" name="j_password">
          <div class="alert alert-danger" id="loginerror" role="alert">
            invalid usermame or password
          </div><br/>
          <button type="submit" class="btn btn-default submit">Sign in</button>
      </form>
      </div>
  </div>

从离子浏览器窗口我收到两个请求(GETPOST)调用到服务器端 login spring security code 下面我粘贴了我的图片

对于Get 请求图片

对于Post 请求图片

GETPOST 请求都只在 ionic 应用程序中自动调用,但同样我只在 spring boot 中运行它,称为 Post 只调用登录安全 url。这是在我的离子应用程序中创建anonymousUser 问题吗?

【问题讨论】:

你在发送 csrf 令牌吗? csrf 令牌已禁用。请看一下。 我认为这是因为会话 ID。 在你的 url 中试试这个 filters="none"。 @jlumietu 不,我粘贴在我的 html 代码上方,是对的还是我需要添加的任何内容 【参考方案1】:

请检查离子浏览器是否保留会话 cookie。恐怕登录正在正确执行并将重定向发送到.defaultSuccessUrl("/login/loginSuccess"),但是当离子浏览器重定向到此页面时,由于会话丢失,无法访问 SecurityContextHolder

【讨论】:

以上是关于Spring安全类工作在不同的端口尝试使用来自apk的有效凭据登录,得到“**anonymousUser**”的主要内容,如果未能解决你的问题,请参考以下文章

端口6000无法访问Spring Boot Swagger REST服务器由于localhost不安全错误

来自 Spring Rest 控制器中 JWT 的安全决策

Spring @Transactional 具有来自不同调用源的不同隔离级别

为啥来自 Spring 的 BCryptPasswordEncoder 为相同的输入生成不同的输出?

802.11i的安全工作机制

spring security 重定向登录时端口 8080 来自哪里?如何将其更改为使用端口 443?