我正在开发一个Angular2应用程序。似乎当我的访问令牌到期时,401 HTTP状态代码在Response对象中变为值0。我收到401 Unauthorized但ERROR Response对象的状态为0.这阻止我捕获401错误并尝试刷新令牌。是什么导致401 HTTP状态代码被更改为HTTP状态代码0?
这是Firefox控制台的截图:
这是我的代码:
get(url: string, options?: RequestOptionsArgs): Observable<any>
{
//console.log('GET REQUEST...', url);
return super.get(url, options)
.catch((err: Response): any =>
{
console.log('************* ERROR Response', err);
if (err.status === 400 || err.status === 422)
{
return Observable.throw(err);
}
//NOT AUTHENTICATED
else if (err.status === 401)
{
this.authConfig.DeleteToken();
return Observable.throw(err);
}
else
{
// this.errorService.notifyError(err);
// return Observable.empty();
return Observable.throw(err);
}
})
// .retryWhen(error => error.delay(500))
// .timeout(2000, new Error('delay exceeded'))
.finally(() =>
{
//console.log('After the request...');
});
}
此代码驻留在扩展Angular2的HTTP的自定义http服务中,因此我可以在一个位置拦截错误。
在谷歌浏览器中,我收到以下错误消息:
XMLHttpRequest无法加载https://api.cloudcms.com/repositories/XXXXXXXXXXXXXXXX/branches/XXXXXXXXXXXXXXXX/nodesXXXXXXXXXXXXXXXX。请求的资源上不存在“Access-Control-Allow-Origin”标头。因此,不允许原点“http://screwtopmedia.local.solutiaconsulting.com”访问。响应的HTTP状态代码为401。
这很令人困惑,因为我在请求中包含了“Access-Control-Allow-Origin”标头。
以下是Google Chrome中收到的结果的图片:
我尝试访问'WWW-Authenticate'响应标头作为捕获401的方法。但是,以下代码返回NULL:
err.headers.get("WWW-Authenticate")
令人费解的是,我遇到了CORS问题,因为在提供有效的访问令牌时我没有收到任何CORS错误。
如何捕获401 HTTP状态代码?为什么401 HTTP状态代码被更改为0?
感谢您的帮助。
答案 0 :(得分:19)
此问题与 CORS请求有关,请参阅this github issue
否&#39;访问控制 - 允许 - 来源&#39;标题出现在请求的上 资源
表示响应标头中需要'Access-Control-Allow-Origin'
。
Angular没有获取任何状态代码,这就是为什么它会导致0
导致浏览器不允许xml parser
因无效而解析response
而导致headers
的原因error response
。
您需要在success
以及def newtons_sqrt(initial_guess, x, threshold=0.0001):
guess = initial_guess
new_guess = (guess+float(x)/guess)/2
while abs(guess-new_guess) > threshold :
guess=new_guess
new_guess = (guess+float(x)/guess)/2
return new_guess
def power(base, exp,threshold=0.00001):
if(exp >= 1): # first go fast!
temp = power(base, exp / 2);
return temp * temp
else: # now deal with the fractional part
low = 0
high = 1.0
sqr = newtons_sqrt(base/2,base)
acc = sqr
mid = high / 2
while(abs(mid - exp) > threshold):
sqr = newtons_sqrt(sqr/2.0,sqr)
if (mid <= exp):
low = mid
acc *= sqr
else:
high = mid
acc *= (1/sqr)
mid = (low + high) / 2;
return acc
print newtons_sqrt(1,8)
print 8**0.5
print power(5,0.76)
print 5**0.76
附加正确的 CORS标题。
答案 1 :(得分:6)
如果cloudcms.com没有在401响应中设置about-section
,那么你无能为力。您必须与他们一起打开支持票,以确认这是否是正常行为。
浏览器中的javascript(FF,Chrome&amp; Safari)我测试过,如果发生CORS错误,则收到任何信息,而不是状态0. Angular2无法控制它。
我创建了一个简单的测试并获得与您相同的结果:
Access-Control-Allow-Origin
经过大量谷歌搜索后,我发现了以下内容(https://github.com/angular/angular.js/issues/3336):
lucassp于2013年8月19日发表评论
我现在找到了一段时间的问题,但我忘了在这里发帖回复。每个响应,即使是错误500,也必须附加CORS标头。如果服务器没有将CORS标头附加到Error 500响应,那么XHR对象不会解析它,因此XHR对象不会有任何响应主体,状态或任何其他响应数据内部。
Firefox网络监视器的结果似乎支持上述原因。
Javascript使用XHRHttpRequest进行http通信。
当XHR回复到达时,浏览器将处理标题,这就是您将看到这些401网络消息的原因。但是,如果XHR回复来自不同的主机,则javascript和响应头不包含CORS头(例如geturl() {
console.log('geturl() clicked');
let headers = new Headers({ 'Content-Type': 'application/xhtml+xml' });
let options = new RequestOptions({ 'headers': headers });
this.http.get(this.url)
.catch((error): any => {
console.log('************* ERROR Response', error);
let errMsg = (error.message) ? error.message :
error.status ? `${error.status} - ${error.statusText}` : 'Web Server error';
return Observable.throw(error);
})
.subscribe(
(i: Response) => { console.log(i); },
(e: any) => { console.log(e); }
);
}
),浏览器将不会将任何信息传递回XHR层。因此,回复正文将完全为空,没有状态(0)。
我使用FF 48.0.1,Chrome 52.0.2743.116和Safari 9.1.2进行了测试,它们都具有相同的行为。
使用浏览器网络监视器检查这些Access-Control-Allow-Origin: *
条目的响应标头,很可能没有401 Unauthorized
标头并导致您遇到的问题。这可能是错误或服务提供商方面的设计。
Access-Control-Allow-Origin
仅响应http标头。有关https://developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS#The_HTTP_response_headers
答案 2 :(得分:5)
我为Cloud CMS工作。我可以确认我们在API调用上正确设置了CORS头。但是,对于401响应,标头未正确设置。这已经解决,本周末将在公共API上提供修复。
BTW如果您使用我们的javascript驱动程序https://github.com/gitana/gitana-javascript-driver而不是直接写入API,则会自动处理重新验证流程,您根本不需要捕获401错误。
答案 3 :(得分:2)
答案 4 :(得分:2)
您应该使用第三方http协议监视器(如CharlesProxy)而不是Chrome开发工具来确认哪些标头实际发送到API服务以及是否返回401。
答案 5 :(得分:1)
我遇到了同样的问题,原因是服务器没有发送正确的响应(即使控制台日志声明401,Angular错误的状态为0)。我的服务器是使用Spring MVC和Spring Security的带有Java应用程序的Tomcat。
现在正在使用以下设置:
SecurityConfig.java
...
protected void configure(HttpSecurity http) throws Exception {
....
http.exceptionHandling()
.accessDeniedHandler(accessDeniedHandler)
.authenticationEntryPoint(authenticationEntryPoint);
// allow CORS option calls
http.authorizeRequests().antMatchers(HttpMethod.OPTIONS, "/**").permitAll();
...
SomeAuthenticationEntryPoint.java
@Component
public class SomeAuthenticationEntryPoint implements AuthenticationEntryPoint {
@Override
public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException authException) throws IOException, ServletException {
HttpStatus responseStatus = HttpStatus.UNAUTHORIZED;
response.sendError(responseStatus.value(), responseStatus.getReasonPhrase());
}
}
的web.xml
<error-page>
<error-code>403</error-code>
<location>/errors/unauthorised</location>
</error-page>
<error-page>
<error-code>401</error-code>
<location>/errors/unauthorised</location>
</error-page>
控制器处理先前定义的/ errors / ...
@RestController
@RequestMapping("/errors")
public class SecurityExceptionController {
@RequestMapping("forbidden")
public void resourceNotFound() throws Exception {
// Intentionally empty
}
@RequestMapping("unauthorised")
public void unAuthorised() throws Exception {
// Intentionally empty
}
}
}
答案 6 :(得分:0)
偶然发现此项目:
我的情况是:
,因为没有允许的CORS(缺少“ Access-Control-Allow-Origin”标头)-Chrome无法将此响应传递到Angular。这样,我可以在Chrome中看到401,但在Angular中看不到。
解决方案很简单(扩展了TimothyBrake的答案)-将丢失的标头添加到错误响应中。在Spring boot中,我输入:response.addHeader("Access-Control-Allow-Origin", "*");
,然后我被整理了出来。
@Component public class JwtUnauthorizedResponseAuthenticationEntryPoint implements AuthenticationEntryPoint { @Override public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException authException) throws IOException { response.addHeader("Access-Control-Allow-Origin", "*"); response.sendError(HttpServletResponse.SC_UNAUTHORIZED, "You would need to provide the Jwt Token to Access This resource"); } }
PS:确保在WebSecurityConfigurerAdapter的HttpSecurity配置中提供了bean。如有疑问,请参见:https://www.baeldung.com/spring-security-basic-authentication。
希望这会有所帮助。