AngularJS SpringSecurity CORS问题
Posted
技术标签:
【中文标题】AngularJS SpringSecurity CORS问题【英文标题】:AngularJS SpringSecurity CORS issue 【发布时间】:2017-02-24 12:17:00 【问题描述】:我正在设置一个 Angular+Spring 安全模块来登录和注册用户。 当我注册用户时,一切正常。注册后的最后一步是自动登录,但我遇到了这个错误:
XMLHttpRequest 无法加载 http//localhost:8080/com-tesis/login。请求的资源上不存在“Access-Control-Allow-Origin”标头。因此,不允许访问 Origin 'http//localhost:9000'。响应的 HTTP 状态代码为 401。
angularJs 端服务:
.factory("sessionAccountService", function($http)
var session = ;
session.login = function(data)
return $http.post("http://localhost:8080/com-tesis/login",
"username="+data.name+"&password="+data.password,
headers: "Access-Control-Allow-Headers":"Content-Type"
).then(function(data)
alert("loggin correcto");
localStorage.setItem("session",);
, function(data)
alert("error login in");
);
;
session.logout = function()
localStorage.removeItem("session");
;
session.isLoggedIn = function()
return localStorage.getItem("session") !== null;
return session;
)
.factory("accountService", function($resource)
var service = ;
service.register = function(account, success, failure)
var Account = $resource("http://localhost:8080/com-tesis/rest/accounts");
Account.save(,account,success,failure);
;
service.userExists = function(account, success, failure)
var Account = $resource("http://localhost:8080/com-tesis/rest/accounts");
var data = Account.get(name:account.name, function()
var accounts = data.accounts;
if (accounts.length !== 0)
success(accounts[0]);
else
failure();
,
failure);
return service;
);
这是在后端实现的 CORS 过滤器:
package tesis.core.security;
import java.io.IOException;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
@Component
public class SimpleCORSFilter implements Filter
private final Logger log = LoggerFactory.getLogger(SimpleCORSFilter.class);
public SimpleCORSFilter()
log.info("SimpleCORSFilter init");
@Override
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain)
throws IOException, ServletException
HttpServletRequest request = (HttpServletRequest) req;
HttpServletResponse response = (HttpServletResponse) res;
response.setHeader("Access-Control-Allow-Origin", request.getHeader("Origin"));
response.setHeader("Access-Control-Allow-Credentials", "true");
response.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE, HEAD");
response.setHeader("Access-Control-Max-Age", "3600");
response.setHeader("Access-Control-Allow-Headers", "Access-Control-Allow-Headers, Origin,Accept, X-Requested-With, Content-Type, Access-Control-Request-Method, Access-Control-Request-Headers");
if (request.getMethod().equals("OPTIONS"))
response.setStatus(HttpServletResponse.SC_OK);
else
chain.doFilter(req, res);
@Override
public void init(FilterConfig filterConfig)
@Override
public void destroy()
这是 web.xml 上的过滤器
<filter>
<filter-name>simpleCORSFilter</filter-name>
<filter-class>
tesis.core.security.SimpleCORSFilter
</filter-class>
</filter>
<filter-mapping>
<filter-name>simpleCORSFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
我很困惑,这是 Chrome 网络请求: req/res
我没有意识到我做错了什么。 谢谢!
编辑: 当我从相同的 url http//localhost:8080/ 发送请求时,效果很好。从 http//localhost:9000 spring 总是返回 SC_UNAUTHORIZED
这是安全配置
package tesis.core.security;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter
@Autowired
private AuthFailure authFailure;
@Autowired
private AuthSuccess authSuccess;
@Autowired
private EntryPointUnauthorizedHandler unauthorizedHandler;
@Autowired
private UserDetailServiceImpl userDetailService;
@Autowired
public void configAuthBuilder(AuthenticationManagerBuilder builder) throws Exception
builder.userDetailsService(userDetailService);
@Override
protected void configure(HttpSecurity http) throws Exception
http
.csrf().disable()
.exceptionHandling()
.authenticationEntryPoint(unauthorizedHandler)
.and()
.formLogin()
.successHandler(authSuccess)
.failureHandler(authFailure)
.and()
.authorizeRequests()
.antMatchers("/**")
.permitAll();
AuthSuccess 和 AuthFailure 类
package tesis.core.security;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.security.core.Authentication;
import org.springframework.security.web.authentication.SimpleUrlAuthenticationSuccessHandler;
import org.springframework.stereotype.Component;
@Component
public class AuthSuccess extends SimpleUrlAuthenticationSuccessHandler
@Override
public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response,
Authentication authentication) throws IOException, ServletException
response.setStatus(HttpServletResponse.SC_OK);
package tesis.core.security;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.authentication.SimpleUrlAuthenticationFailureHandler;
import org.springframework.stereotype.Component;
@Component
public class AuthFailure extends SimpleUrlAuthenticationFailureHandler
@Override
public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response,
AuthenticationException exception) throws IOException, ServletException
response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
【问题讨论】:
感谢您的回复,无论如何,当我从相同的 url http//localhost:8080/ 发送请求时效果很好。从 http//localhost:9000 spring 总是返回 SC_UNAUTHORIZED。我编辑了答案 @Fede:将服务器日志添加到您的问题中。有没有例外? 【参考方案1】:我终于找到了解决方案。首先,为了解决 401 错误,我重写了请求,如下所示:401 solution
之后又出现了一个新的错误:
请求的资源 Origin 上没有“Access-Control-Allow-Origin”标头,因此不允许访问。
然后,阅读 Spring 文档,我意识到我必须具体说明 spring 使用哪个标头。线索在这里:Spring Doc: header-static
所以,这是已修复的 SecurityConfig 文件:
package tesis.core.security;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.web.authentication.AuthenticationFailureHandler;
import org.springframework.security.web.authentication.SimpleUrlAuthenticationFailureHandler;
import org.springframework.security.web.header.writers.StaticHeadersWriter;
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter
@Autowired
private AuthFailure authFailure;
@Autowired
private AuthSuccess authSuccess;
@Autowired
private EntryPointUnauthorizedHandler unauthorizedHandler;
@Autowired
private UserDetailServiceImpl userDetailService;
@Autowired
public void configAuthBuilder(AuthenticationManagerBuilder builder) throws Exception
builder.userDetailsService(userDetailService);
@Bean
public AuthenticationFailureHandler authenticationFailureHandler()
return new SimpleUrlAuthenticationFailureHandler();
@Override
protected void configure(HttpSecurity http) throws Exception
http
.csrf().disable()
.headers().addHeaderWriter(new StaticHeadersWriter("Access-Control-Allow-Origin","*"))
.and()
.exceptionHandling()
.authenticationEntryPoint(unauthorizedHandler)
.and()
.formLogin()
.successHandler(authSuccess)
.failureHandler(authFailure)
.and()
.authorizeRequests()
.antMatchers("/**")
.permitAll();
谢谢大家。
【讨论】:
以上是关于AngularJS SpringSecurity CORS问题的主要内容,如果未能解决你的问题,请参考以下文章
AngularJS SpringSecurity CORS问题
带有 Spring Security 的 AngularJS Web 应用程序
Spring Security + AngularJS:POST 请求
Spring Security 401 - 使用 / Angularjs 调用 restful 服务