我需要使用基本身份验证发送授权请求。我已经使用jquery成功实现了这一点。但是当我得到401错误时,基本的auth浏览器弹出窗口被打开,并且没有调用jquery ajax错误回调。
答案 0 :(得分:41)
我最近也面临这个问题。由于在401
(基本或摘要身份验证)的情况下,您无法更改浏览器显示弹出窗口的默认行为,因此有两种方法可以解决这样:
401
。返回200
代码并在jQuery客户端中处理它。将用于授权的方法更改为标题中的自定义值。浏览器将显示 Basic 和 Digest 的弹出窗口。您必须在客户端和服务器上更改它。
headers : {
"Authorization" : "BasicCustom"
}
另请参阅this以获取使用基本身份验证的jQuery的示例。
答案 1 :(得分:31)
返回通用400状态代码,然后处理该客户端。
或者您可以保留401,而不是返回WWW-Authenticate标头,这正是浏览器通过身份验证弹出窗口响应的内容。如果缺少WWW-Authenticate标头,则浏览器将不会提示输入凭据。
答案 2 :(得分:17)
您可以使用如下所示的请求网址来禁止基本身份验证弹出窗口:
https://username:password@example.com/admin/...
如果您收到401错误(用户名或密码错误),将使用jquery错误回调正确处理。它可能会导致一些安全问题(如果是http协议而不是https),但它可以正常工作。
UPD:此解决方案支持将在Chrome 59中删除
答案 3 :(得分:9)
正如其他人所指出的,改变浏览器行为的唯一方法是确保响应不包含401状态代码,或者如果包含,则不包括WWW-Authenticate: Basic
标头。由于更改状态代码不是非常语义和不可取的,因此一种好方法是删除WWW-Authenticate
标头。如果您不能或不想修改您的Web服务器应用程序,您始终可以通过Apache提供服务或代理它(如果您尚未使用Apache)。
这是Apache重写响应以删除WWW-Authenticate头的配置请求包含的IFF包含头X-Requested-With: XMLHttpRequest
(默认情况下由主要的Javascript框架设置,如JQuery / AngularJS等。 ..)AND响应包含标题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>
答案 4 :(得分:5)
如果您使用的是IIS服务器,则可以设置IIS URL重写(v2),以便在请求的URL上将WWW-Authentication
标头重写为None
。
您要更改的值为response_www_authenticate
。
如果您需要更多信息,请添加评论,我将发布web.config文件。
答案 5 :(得分:3)
将X-Requested-With:XMLHttpRequest与您的请求标头一起使用。 因此响应头不包含WWW-Authenticate:Basic。
beforeSend: function (xhr) {
xhr.setRequestHeader('Authorization', ("Basic "
.concat(btoa(key))));
xhr.setRequestHeader('X-Requested-With', 'XMLHttpRequest');
},
答案 6 :(得分:2)
或者,如果您可以自定义服务器响应,则可以返回403 Forbidden。
浏览器不会打开身份验证弹出窗口,并且将调用jquery回调。
答案 7 :(得分:2)
如果删除了WWW-Authenticate标头,那么您将无法获得凭据的缓存,并且不会在请求中返回Authorization标头。这意味着现在您必须为您生成的每个新请求输入凭据。
答案 8 :(得分:1)
在Safari中,您可以使用同步请求来避免浏览器显示弹出窗口。当然,同步请求只应在这种情况下用于检查用户凭据...您可以在发送实际请求之前使用此类请求,如果内容(已发送或已接收)非常繁重,可能会导致糟糕的用户体验。 / p>
constructor(props) {
super(props);
this.state = {
location: false,
};
}
componentDidMount() {
this.askForUserPermissionToGetCurrentLocation();
}
async askForUserPermissionToGetCurrentLocation() {
// Ask for user's permission to access location settings
let { status } = await
Expo.Permissions.askAsync(Expo.Permissions.LOCATION);
console.log(status);
// User denied access
if (status !== "granted") {
console.log("denied");
// Otherwise, access granted
} else {
console.log("permission granted");
// Get the location
let location = await Expo.Location.getCurrentPositionAsync({});
console.log(location);
this.setState({ location: location });
}
答案 9 :(得分:0)
创建一个/ login url,而不是通过GET接受“user”和“password”参数,并且不需要基本的auth。在这里,使用php,node,java,whatever和解析你的passwd文件并匹配参数(user / pass)。如果匹配则重定向到http://user:pass@domain.com/(这将在您的浏览器上设置凭据)如果没有,则发送401响应(没有WWW-Authenticate标头)。
答案 10 :(得分:0)
从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);
}
}
};
}
答案 11 :(得分:0)
尚未探讨修复的原因或范围,但我发现如果我正在执行 fetch
请求并添加标头 x-requested-with: 'XMLHttpRequest'
,我将不再在 Chrome 中获得弹出式身份验证框并且不需要更改服务器。它正在与节点 http
库对话。看起来 WWW-Authenticate
标头从服务器返回,但 Chrome 处理它的方式不同。可能是指定的。
示例:
fetch(url, {
headers: {
Authorization: `Basic ${auth}`,
'x-requested-with': 'XMLHttpRequest'
},
credentials: 'include'
})