我需要使用基本身份验证发送授权请求。我已经使用jquery成功实现了这一点。但是,当我收到401错误时,将打开基本身份验证浏览器弹出窗口,并且不会调用jquery ajax错误回调。
我需要使用基本身份验证发送授权请求。我已经使用jquery成功实现了这一点。但是,当我收到401错误时,将打开基本身份验证浏览器弹出窗口,并且不会调用jquery ajax错误回调。
Answers:
我最近也面临这个问题。由于您无法更改浏览器的默认行为401
(在基本身份验证或摘要身份验证的情况下)显示弹出窗口,因此有两种方法可以解决此问题:
401
。200
而是返回一个代码,并在您的jQuery客户端中进行处理。将用于授权的方法更改为标头中的自定义值。浏览器将显示Basic和Digest的弹出窗口。您必须在客户端和服务器上都进行更改。
headers : {
"Authorization" : "BasicCustom"
}
也请看一看这对于使用jQuery使用基本身份验证的一个例子。
<security:http-basic/>
,则无需定义,basicAuthenticationFilter
但应将其定义为<security:http-basic entry-point-ref="myBasicAuthenticationEntryPoint"/>
。
401
和 WWW-Authenticate:Bearer WWW-Authenticate:NTLM WWW-Authenticate:Negotiate
你知道为什么那会是
返回通用的400状态代码,然后处理该客户端。
或者,您可以保留401,而不返回WWW-Authenticate标头,这实际上是浏览器通过身份验证弹出窗口响应的内容。如果缺少WWW-Authenticate标头,则浏览器将不提示输入凭据。
res.removeHeader('www-authenticate'); // prevents browser from popping up a basic auth window.
您可以使用以下请求网址禁止基本身份验证弹出窗口:
https://username:password@example.com/admin/...
如果您收到401错误(错误的用户名或密码),则会通过jquery错误回调正确处理。它可能会导致一些安全问题(如果使用HTTP协议而不是https),但是它是可行的。
UPD:此解决方案支持将在Chrome 59中删除
正如其他人指出的那样,更改浏览器行为的唯一方法是确保响应不包含401状态代码,或者如果响应不包含401 WWW-Authenticate: Basic
标头。由于更改状态码不是很语义化也不可取,因此一种好的方法是删除WWW-Authenticate
标头。如果您不能或不想修改Web服务器应用程序,则可以始终通过Apache服务或代理它(如果您尚未使用Apache)。
这是Apache的配置,用于重写响应以删除请求包含的WWW-Authenticate标头IFF,该标头包含标头X-Requested-With: XMLHttpRequest
(默认情况下由主要的Javascript框架(如JQuery / AngularJS等)设置标头),并且响应包含标头WWW-Authenticate: Basic
。
已在Apache 2.4上测试(不确定它是否可与2.2一起使用)。这取决于mod_headers
正在安装的模块。(在Debian / Ubuntu上,sudo a2enmod headers
然后重新启动Apache)
<Location />
# Make sure that if it is an XHR request,
# we don't send back basic authentication header.
# This is to prevent the browser from displaying a basic auth login dialog.
Header unset WWW-Authenticate "expr=req('X-Requested-With') == 'XMLHttpRequest' && resp('WWW-Authenticate') =~ /^Basic/"
</Location>
proxy_hide_header WWW-Authenticate;
将X-Requested-With:XMLHttpRequest与您的请求标头一起使用。因此,响应标头将不包含WWW-Authenticate:Basic。
beforeSend: function (xhr) {
xhr.setRequestHeader('Authorization', ("Basic "
.concat(btoa(key))));
xhr.setRequestHeader('X-Requested-With', 'XMLHttpRequest');
},
如果使用的是IIS服务器,则可以设置IIS URL重写(v2)以将WWW-Authentication
标头重写为None
所请求的URL。
您要更改的值为response_www_authenticate
。
如果您需要更多信息,请添加评论,然后我将发布web.config文件。
如果删除了WWW-Authenticate标头,则将不会获得凭据的缓存,也不会在请求中返回Authorization标头。这意味着现在您将必须为生成的每个新请求输入凭据。
另外,如果您可以自定义服务器响应,则可以返回403 Forbidden。
浏览器将不会打开身份验证弹出窗口,并且将调用jquery回调。
在Safari中,您可以使用同步请求来避免浏览器显示弹出窗口。当然,在这种情况下,同步请求仅应用于检查用户凭据...您可以在发送实际请求之前使用此类请求,如果内容(已发送或已接收)非常繁重,可能会导致不良的用户体验。
var xmlhttp=new XMLHttpRequest;
xmlhttp.withCredentials=true;
xmlhttp.open("POST",<YOUR UR>,false,username,password);
xmlhttp.setRequestHeader("Content-type","application/x-www-form-urlencoded");
xmlhttp.setRequestHeader('X-Requested-With', 'XMLHttpRequest');
创建一个/ login网址,然后通过GET接受“ user”和“ password”参数,并且不需要基本身份验证。在这里,使用php,node,java等工具,解析您的passwd文件并匹配参数(用户/密码)。如果匹配,则重定向到http:// user:pass@domain.com/(这将在您的浏览器上设置凭据),如果不匹配,则发送401响应(不带WWW-Authenticate标头)。
从Spring Boot的背面,我使用了自定义的BasicAuthenticationEntryPoint:
@Override
protected void configure(HttpSecurity http) throws Exception {
http.cors().and().authorizeRequests()
...
.antMatchers(PUBLIC_AUTH).permitAll()
.and().httpBasic()
// https://www.baeldung.com/spring-security-basic-authentication
.authenticationEntryPoint(authBasicAuthenticationEntryPoint())
...
@Bean
public BasicAuthenticationEntryPoint authBasicAuthenticationEntryPoint() {
return new BasicAuthenticationEntryPoint() {
{
setRealmName("pirsApp");
}
@Override
public void commence
(HttpServletRequest request, HttpServletResponse response, AuthenticationException authEx)
throws IOException, ServletException {
if (request.getRequestURI().equals(PUBLIC_AUTH)) {
response.sendError(HttpStatus.PRECONDITION_FAILED.value(), "Wrong credentials");
} else {
super.commence(request, response, authEx);
}
}
};
}