Spring-boot-oauth2-angularjs,会话到期后CORS出错,并重定向到oauth2服务器
我有一个前端应用程序,在服务器端使用Spring引导、Spring security oauth2,在客户端使用AngularJs。我还使用第三方oauth2服务器。我的问题是,在应用程序会话到期后,SpingSecurity将所有请求重定向到“/login”(这正是应该的方式),我在响应头的auth server页面上获得了302状态代码,其中包含要重定向的位置。但是重定向没有发生,因为我得到错误: XMLHttpRequest无法加载****://bla-bla/oauth/authorize?客户端\u id=…和someAuthStuff。请求的资源上不存在“Access Control Allow Origin”标头。因此,不允许访问源“***://MyiPAddress:8084” 问题是,为什么第一次进入应用程序或刷新页面或注销和新登录时不涉及此类错误,而且一切正常,但只有当我获得会话超时时(例如,我从dead view发出ajax请求),才会发生CORS错误:-( 我复制以下步骤:Spring-boot-oauth2-angularjs,会话到期后CORS出错,并重定向到oauth2服务器,angularjs,ajax,spring,spring-mvc,oauth,Angularjs,Ajax,Spring,Spring Mvc,Oauth,我有一个前端应用程序,在服务器端使用Spring引导、Spring security oauth2,在客户端使用AngularJs。我还使用第三方oauth2服务器。我的问题是,在应用程序会话到期后,SpingSecurity将所有请求重定向到“/login”(这正是应该的方式),我在响应头的auth server页面上获得了302状态代码,其中包含要重定向的位置。但是重定向没有发生,因为我得到错误: XMLHttpRequest无法加载****://bla-bla/oauth/authoriz
public class SimpleCORSFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
HttpServletResponse res = (HttpServletResponse) response;
res.setHeader("Access-Control-Allow-Origin", "*");
res.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE, PUT");
res.setHeader("Access-Control-Max-Age", "3600");
res.setHeader("Access-Control-Allow-Headers", "Authorization, Content-Type, Accept, x-requested-with, Cache-Control");
chain.doFilter(request, res);
}
@Override
public void destroy() {
}
}
@EnableOAuth2Sso
@Configuration
public class CustomWebSecurityConfigurerAdapter extends WebSecurityConfigurerAdapter {
@Override
public void configure(HttpSecurity http) throws Exception {
http.logout()
.and().antMatcher("/**")
.authorizeRequests()
.anyRequest().authenticated()
.and().csrf().disable()
.addFilterBefore(new SimpleCORSFilter(), ChannelProcessingFilter.class);
}
}
public class SimpleCORSFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
HttpServletResponse res = (HttpServletResponse) response;
res.setHeader("Access-Control-Allow-Origin", "*");
res.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE, PUT");
res.setHeader("Access-Control-Max-Age", "3600");
res.setHeader("Access-Control-Allow-Headers", "Authorization, Content-Type, Accept, x-requested-with, Cache-Control");
chain.doFilter(request, res);
}
@Override
public void destroy() {
}
}
@EnableOAuth2Sso
@Configuration
public class CustomWebSecurityConfigurerAdapter extends WebSecurityConfigurerAdapter {
@Override
public void configure(HttpSecurity http) throws Exception {
http.logout()
.and().antMatcher("/**")
.authorizeRequests()
.anyRequest().authenticated()
.and().csrf().disable()
.addFilterBefore(new SimpleCORSFilter(), ChannelProcessingFilter.class);
}
}
请求URL:**//MyiPAddress:8084/appname/login
请求方法:获取
状态代码:302已找到
远程地址:MyiPAddress:8084
响应标题:
public class SimpleCORSFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
HttpServletResponse res = (HttpServletResponse) response;
res.setHeader("Access-Control-Allow-Origin", "*");
res.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE, PUT");
res.setHeader("Access-Control-Max-Age", "3600");
res.setHeader("Access-Control-Allow-Headers", "Authorization, Content-Type, Accept, x-requested-with, Cache-Control");
chain.doFilter(request, res);
}
@Override
public void destroy() {
}
}
@EnableOAuth2Sso
@Configuration
public class CustomWebSecurityConfigurerAdapter extends WebSecurityConfigurerAdapter {
@Override
public void configure(HttpSecurity http) throws Exception {
http.logout()
.and().antMatcher("/**")
.authorizeRequests()
.anyRequest().authenticated()
.and().csrf().disable()
.addFilterBefore(new SimpleCORSFilter(), ChannelProcessingFilter.class);
}
}
访问控制允许标头:授权、内容类型、接受、x-requested-with、缓存控制
访问控制允许方法:POST、GET、OPTIONS、DELETE、PUT
访问控制允许来源:*
访问控制最大年龄:3600
缓存控制:无缓存,无存储,最大年龄=0,必须重新验证
位置://authserver/oauth/authorize?客户端id=******重定向uri=*://myipAddress:8084/appname/login&response\u type=code&state=BIQ68y
Pragma:没有缓存
服务器:ApacheCoote/1.1
设置Cookie:JSESSIONID=05D39263EEF7EC9E24AEE8E1E6693748;路径=/appname/;仅HttpOnly
X-Content-Type-Options:nosniff
X帧选项:拒绝
X-XSS-保护:1;模式=块
CORS过滤器:
public class SimpleCORSFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
HttpServletResponse res = (HttpServletResponse) response;
res.setHeader("Access-Control-Allow-Origin", "*");
res.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE, PUT");
res.setHeader("Access-Control-Max-Age", "3600");
res.setHeader("Access-Control-Allow-Headers", "Authorization, Content-Type, Accept, x-requested-with, Cache-Control");
chain.doFilter(request, res);
}
@Override
public void destroy() {
}
}
@EnableOAuth2Sso
@Configuration
public class CustomWebSecurityConfigurerAdapter extends WebSecurityConfigurerAdapter {
@Override
public void configure(HttpSecurity http) throws Exception {
http.logout()
.and().antMatcher("/**")
.authorizeRequests()
.anyRequest().authenticated()
.and().csrf().disable()
.addFilterBefore(new SimpleCORSFilter(), ChannelProcessingFilter.class);
}
}
安全配置:
public class SimpleCORSFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
HttpServletResponse res = (HttpServletResponse) response;
res.setHeader("Access-Control-Allow-Origin", "*");
res.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE, PUT");
res.setHeader("Access-Control-Max-Age", "3600");
res.setHeader("Access-Control-Allow-Headers", "Authorization, Content-Type, Accept, x-requested-with, Cache-Control");
chain.doFilter(request, res);
}
@Override
public void destroy() {
}
}
@EnableOAuth2Sso
@Configuration
public class CustomWebSecurityConfigurerAdapter extends WebSecurityConfigurerAdapter {
@Override
public void configure(HttpSecurity http) throws Exception {
http.logout()
.and().antMatcher("/**")
.authorizeRequests()
.anyRequest().authenticated()
.and().csrf().disable()
.addFilterBefore(new SimpleCORSFilter(), ChannelProcessingFilter.class);
}
}
在ajax请求后记录:
public class SimpleCORSFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
HttpServletResponse res = (HttpServletResponse) response;
res.setHeader("Access-Control-Allow-Origin", "*");
res.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE, PUT");
res.setHeader("Access-Control-Max-Age", "3600");
res.setHeader("Access-Control-Allow-Headers", "Authorization, Content-Type, Accept, x-requested-with, Cache-Control");
chain.doFilter(request, res);
}
@Override
public void destroy() {
}
}
@EnableOAuth2Sso
@Configuration
public class CustomWebSecurityConfigurerAdapter extends WebSecurityConfigurerAdapter {
@Override
public void configure(HttpSecurity http) throws Exception {
http.logout()
.and().antMatcher("/**")
.authorizeRequests()
.anyRequest().authenticated()
.and().csrf().disable()
.addFilterBefore(new SimpleCORSFilter(), ChannelProcessingFilter.class);
}
}
2016-04-04 14:10:42.613调试5428---[o-8084-exec-144]o.s.s.w.u.matcher.AntPathRequestMatcher:检查请求的匹配:'/login';对照'/login'
2016-04-04 14:10:42.613调试5428---[o-8084-exec-144]uth2ClientAuthenticationProcessingFilter:请求处理身份验证
2016-04-04 14:10:42.615调试5428---[o-8084-exec-144]w.c.HttpSessionSecurityContextRepository:SecurityContext为空或内容为匿名-上下文将不会存储在HttpSession中。
2016-04-04 14:10:42.657调试5428---[o-8084-exec-144]s.s.w.c.SecurityContextPersistenceFilter:SecurityContextHolder现在已清除,请求处理已完成
2016-04-04 14:10:42.658调试5428---[o-8084-exec-144]o.s.s.web.DefaultRedirectStrategy:重定向到'***://authserver/oauth/authorize?client_id=*********和redirect_uri=***://myipAddress:8084/appname/login&response_type=code&state=iNdnBk'
我认为您需要将@EnableWebSecurity注释添加到您的CustomWebSecurity配置适配器。此外,我尝试了另一种方法,并以如下方式放置过滤器:
@Override
public void configure(HttpSecurity http) throws Exception {
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
CorsConfiguration config = new CorsConfiguration();
config.setAllowCredentials(true);
config.addAllowedOrigin("*");
config.addAllowedHeader("*");
config.addAllowedMethod("GET");
config.addAllowedMethod("PUT");
source.registerCorsConfiguration("/**", config);
CorsFilter filter = new CorsFilter(source);
http
.logout()
.and().antMatcher("/**")
.authorizeRequests()
.anyRequest().authenticated()
.and().csrf().disable()
.addFilterBefore(filter, ChannelProcessingFilter.class);
}
但是它也没有帮助,响应中的CORS标题都消失了!我认为原因不在标题中,而是在响应中的状态代码302中。我如何才能得到401而不是302?我钩住了这个注释,但问题仍然存在。我发现了几个类似的情况,以及302下的所有问题都在响应中重定向。不幸的是,所有的解决方案都不能解决问题