我正在开发应用程序,我使用Spring MVC作为后端,Angular5作为前端。我一直坚持使用Auth2安全层,包括跨源资源共享。我的CORS过滤器实现如下所示:
@Component
@Order(Ordered.HIGHEST_PRECEDENCE)
@WebFilter("/*")
public class WebSecurityCorsFilter 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");
if ("OPTIONS".equalsIgnoreCase(((HttpServletRequest) request).getMethod())) {
res.setStatus(HttpServletResponse.SC_OK);
} else {
chain.doFilter(request, res);
}
}
@Override
public void destroy() {
}
}
我的工作几乎正常,我能够获取access_token并使用它从ResourcesServer获取受保护的数据:
{ “的access_token”: “4fcef1f8-4306-4047-9d4d-1c3cf74ecc44”, “token_type”: “承载”, “refresh_token”: “397016eb-dfb0-4944-a2e0-50c3bd07c250”, “expires_in”:29, “范围”:“读 写信任“}
当我尝试使用过期令牌处理请求时,问题就开始了。在这种情况下,我无法通过Angular捕获正确的ErrorResponeCode。而不是401我Angular HttpClient得到“未知错误”状态:0。
看起来问题出在CORS策略中,其中ErrorResponse不包含neccessery头,如Access-Control-Allow-Origin(...)
无法加载http://localhost:8030/api/xxxx:否 请求中存在“Access-Control-Allow-Origin”标头 资源。因此不允许来源“http://localhost:8070” 访问。响应的HTTP状态代码为401。
ErrorResponse Headers - Screenshot
我已经在Spring MVC中搜索了如何为ErorrResponse(InvalidTokenException等)启用CORS。我尝试了各种方法:accessDeniedHandler和setExceptionTranslator但没有成功。我自己努力找到解决方案,但我是Spring的初学者。我不确定这是否可行。
ANGULAR(更新)
@hrdkisback,这不是角度问题,无论如何这是我的代码:
@Injectable()
export class HttpInterceptorService implements HttpInterceptor {
addToken(req: HttpRequest<any>, oauthService: AuthenticationService): HttpRequest<any> {
if(oauthService.isTokenExist()){
return req.clone({ setHeaders: { Authorization: 'Bearer ' + oauthService.getAccessToken() }})
}
return req;
}
intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpSentEvent | HttpHeaderResponse | HttpProgressEvent | HttpResponse<any> | HttpUserEvent<any>> {
let oauthService = this.inj.get(AuthenticationService);
return next.handle(this.addToken(req,oauthService))
.do((event: HttpEvent<any>) => {
if (event instanceof HttpResponse) {
// process successful responses here
}
}, (error: any) => {
if (error instanceof HttpErrorResponse) {
// Error
console.log(error);
}
});
}
}
答案 0 :(得分:2)
在我在ResourcesServer配置级别添加我的CORS过滤器之后问题解决了:
适合我的正确配置!
@Configuration
@EnableResourceServer
public class ResourceServerConfig extends ResourceServerConfigurerAdapter {
@Override
public void configure(HttpSecurity http) throws Exception {
http
.addFilterAfter(new WebSecurityCorsFilter(), CsrfFilter.class)
...
}
....
}
在我之前的配置中,我以相同的方式添加了过滤器,但是在MVC安全配置的顶层,这是我的问题的根本原因:
导致我的问题的先前配置
@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Override
public void configure(HttpSecurity http) throws Exception {
http
.addFilterAfter(new WebSecurityCorsFilter(), CsrfFilter.class)
...
}
....
}
答案 1 :(得分:0)
我遇到了同样的问题..我正在尝试使用Angular 5进行Basic Auth。 问题是您没有在错误响应上添加CORS标头。 这就是我做的事情
@Component
public class AuthEntryPoint extends BasicAuthenticationEntryPoint {
@Override
public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException authEx)
throws IOException, ServletException {
response.addHeader("WWW-Authenticate", "Basic realm=" +getRealmName());
response.addHeader("Access-Control-Allow-Origin", "http://localhost:4200");
response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
PrintWriter writer = response.getWriter();
writer.println("HTTP Status 401 - " + authEx.getMessage());
}
}
那就行了!