【问题标题】:Spring Security not reusing authentication data with Spring Session EnableRedisHttpSessionSpring Security 不使用 Spring Session EnableRedisHttpSession 重用身份验证数据
【发布时间】:2015-06-05 10:07:38
【问题描述】:

我能够使用来自https://github.com/dsyer/spring-security-angular/blob/master/vanilla/README.md 的示例 Spring Boot Groovy Maven 实现成功运行此配置。当应用程序代码在 Java 和 Gradle 2.3 中实现时,它不起作用。在这种情况下,OPTIONS 响应有一个新的 X-Auth-Token。

尝试将提供的 maven 构建与我的 java 类一起使用,但仍然得到相同的 OPTIONS 401 未经授权的响应。所以这不是 Gradle 问题。

将两个 ResourceApplication Groovy 类复制到我的 Gradle 构建中,Angular ui 成功获得 OPTIONS 200 OK。所以java中的Spring CORS过滤器存在问题。

我有用于 java 和 groovy 的 Gradle 插件、sourceCompatibility 和 目标兼容性 = 1.7

java 版本“1.8.0_31” Java(TM) SE 运行时环境 (build 1.8.0_31-b13) Java HotSpot(TM) 64 位服务器 VM(内部版本 25.31-b07,混合模式)

开发者控制台日志验证相同的令牌是从 ui 服务器发送并由 angular 客户端接收的,但报告了 CORS 错误。

跨域请求被阻止:同源策略不允许读取位于http://localhost:9000/ 的远程资源。这可以通过将资源移动到同一域或启用 CORS 来解决。本地主机:9000

@SpringBootApplication
@RestController
@EnableRedisHttpSession
public class AngularDemoApplication {
@RequestMapping("/user")
public Principal user(Principal user) {
  return user;
}

@RequestMapping("/token")
@ResponseBody
public Map<String,String> token(HttpSession session) {
  logger.debug("********** TOKEN *********** = "+session.getId());
  return Collections.singletonMap("token", session.getId());
}

@Configuration
@Order(SecurityProperties.ACCESS_OVERRIDE_ORDER)
protected static class SecurityConfiguration extends WebSecurityConfigurerAdapter {
  @Override
  protected void configure(HttpSecurity http) throws Exception {
      http.httpBasic().and().logout().and().authorizeRequests()
        .antMatchers("/index.html", "/home.html", "/login.html", "/").permitAll()
        .anyRequest().authenticated().and().csrf().csrfTokenRepository(csrfTokenRepository())
        .and().addFilterAfter(csrfHeaderFilter(), CsrfFilter.class);
  }

  private Filter csrfHeaderFilter() {
        return new OncePerRequestFilter() {
            @Override
            protected void doFilterInternal(HttpServletRequest request,
                    HttpServletResponse response, FilterChain filterChain)
                    throws ServletException, IOException {
                CsrfToken csrf = (CsrfToken) request.getAttribute(CsrfToken.class
                        .getName());
                if (csrf != null) {
                    Cookie cookie = WebUtils.getCookie(request, "XSRF-TOKEN");
                    String token = csrf.getToken();
                    if (cookie == null || token != null
                            && !token.equals(cookie.getValue())) {
                        cookie = new Cookie("XSRF-TOKEN", token);
                        cookie.setPath("/");
                        response.addCookie(cookie);
                    }
                }
                filterChain.doFilter(request, response);
            }
        };
    }


  private CsrfTokenRepository csrfTokenRepository() {
      HttpSessionCsrfTokenRepository repository = new HttpSessionCsrfTokenRepository();
      repository.setHeaderName("X-XSRF-TOKEN");
      return repository;
  }
}

public static void main(String[] args) {
    SpringApplication.run(AngularDemoApplication.class, args);
}

}

@SpringBootApplication
@RestController
@EnableRedisHttpSession
public class ResourceApplication {

@RequestMapping("/")
public Map<String,Object> home() {
      Map<String,Object> model = new HashMap<String,Object>();
      model.put("id", UUID.randomUUID().toString());
      model.put("content", "Hello World");
      return model;
}


@Bean
public HeaderHttpSessionStrategy sessionStrategy() {
    return new HeaderHttpSessionStrategy();
 }

public static void main(String[] args) {
    SpringApplication.run(ResourceApplication.class, args);
}

}

@Component
@Order(Ordered.HIGHEST_PRECEDENCE)
class CorsFilter implements Filter {

@Override
public void doFilter(ServletRequest req, ServletResponse res,
        FilterChain chain) throws IOException, ServletException {
    HttpServletResponse response = (HttpServletResponse) res;
    HttpServletRequest request = (HttpServletRequest) req;
    response.setHeader("Access-Control-Allow-Origin", "*");
    response.setHeader("Access-Control-Allow-Methods", "POST, PUT, GET, OPTIONS, DELETE");
    response.setHeader("Access-Control-Max-Age", "3600");
    response.setHeader("Access-Control-Allow-Headers", "x-auth-token, x-requested-with");
    if (request.getMethod() != "OPTIONS" ) {
        chain.doFilter(req, res);
    } else {
         }

}

@Override
public void init(FilterConfig filterConfig) throws ServletException {
    // TODO Auto-generated method stub

}

@Override
public void destroy() {
    // TODO Auto-generated method stub

}

}

Groovy 版本:

请求方法:选项
状态码:200 OK

请求标头:
主机:本地主机:9000
用户代理:Mozilla/5.0 (Windows NT 6.1; WOW64; rv:36.0) Gecko/20100101 Firefox/36.0
接受:text/html,application/xhtml+xml,application/xml;q=0.9,/;q=0.8
接受语言:en-US,en;q=0.5
接受编码:gzip、放气
来源:本地主机:8080
访问控制请求方法:GET
访问控制请求标头:x-auth-token、x-requested-with
连接:保持活动

响应标头:
访问控制允许标头:x-auth-token、x-requested-with
访问控制允许方法:POST、PUT、GET、OPTIONS、DELETE
访问控制允许来源:*
访问控制最大年龄:3600
内容长度:0
日期:格林威治标准时间 2015 年 3 月 31 日星期二 21:20:28
服务器:Apache-Coyote/1.1

请求方法:GET
状态码:200 OK

请求标头:
主机:本地主机:9000 用户代理:Mozilla/5.0 (Windows NT 6.1; WOW64; rv:36.0) Gecko/20100101 Firefox/36.0
接受:application/json, text/plain, /
接受语言:en-US,en;q=0.5
接受编码:gzip、放气
X-Auth-令牌:80e0c2d2-dab4-435d-886e-ae28bc8e636f
X-Requested-With: XMLHttpRequest

响应标头:
访问控制允许标头:x-auth-token、x-requested-with
访问控制允许方法:POST、PUT、GET、OPTIONS、DELETE
访问控制允许来源:*
访问控制最大年龄:3600
内容类型:application/json;charset=UTF-8
日期:格林威治标准时间 2015 年 3 月 31 日星期二 21:20:28
服务器:Apache-Coyote/1.1
严格的传输安全性: max-age=31536000 ;包括子域
传输编码:分块
参考:本地主机:8080/
来源:本地主机:8080
连接:保持活动

Redis 服务器密钥:
1)“春天:会话:过期:1427838660000”
2)“弹簧:会话:会话:80e0c2d2-dab4-435d-886e-ae28bc8e636f”

Java 版本:

请求方法:选项
状态码:401 未授权

请求标头:
主机:本地主机:9000
用户代理:Mozilla/5.0 (Windows NT 6.1; WOW64; rv:36.0) Gecko/20100101 Firefox/36.0
接受:text/html,application/xhtml+xml,application/xml;q=0.9,/;q=0.8
接受语言:en-US,en;q=0.5
接受编码:gzip、放气
来源:本地主机:8080
访问控制请求方法:GET
访问控制请求标头:x-auth-token、x-requested-with
连接:保持活动

响应标头:
访问控制允许标头:x-auth-token、x-requested-with
访问控制允许方法:POST、PUT、GET、OPTIONS、DELETE
访问控制允许来源:*
访问控制最大年龄:3600
允许:GET、HEAD、POST、PUT、DELETE、TRACE、OPTIONS、PATCH
内容长度:0
日期:格林威治标准时间 2015 年 3 月 31 日星期二 20:50:26
服务器:Apache-Coyote/1.1
严格的传输安全性: max-age=31536000 ;包括子域
WWW-Authenticate: Basic realm="Spring"
X-Auth-Token:8af7e1f4-e723-4ce6-8d21-54a7b10369f8

Redis 服务器密钥:
1)“弹簧:会话:会话:8af7e1f4-e723-4ce6-8d21-54a7b10369f8”
2)“春天:会话:过期:1427836860000”
3)“弹簧:会话:会话:c6a6cc31-eddc-40dd-99de-a6e1eecbf519”

【问题讨论】:

    标签: java angularjs spring-security spring-boot spring-session


    【解决方案1】:

    在 Java 中“!=”运算符与 Groovy 不同。要进行字符串对象比较,请使用 equals 方法。即

    if( !"OPTIONS".equals(request.getMethod()))   
    

    【讨论】:

      猜你喜欢
      • 2019-05-20
      • 2011-11-14
      • 2015-06-18
      • 2016-01-11
      • 2021-09-05
      • 1970-01-01
      • 2011-06-04
      • 2016-09-09
      • 2012-11-27
      相关资源
      最近更新 更多