读Http权威指南时有这样一段描述:
如果服务器希望在为用户提供对站点的访问之前,先行登录,可以向浏览器回送一条 HTTP 响应代码 401 Login Required。然后,浏览器会显示一个登录对话框,并
用 Authorization 首部在下一条对服务器的请求中提供这些信息
实践一下现代浏览器会不会真的这样
后台使用Koa,前台直接写html,先使用jsonp,通过script标签来获取数据,返回401
index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<button class="target">测试</button>
<script>
var target = document.querySelector('.target');
function callback(arg) {
console.log(arg)
}
target.addEventListener('click', function () {
let script = document.createElement('script')
script.src = 'http://localhost:3000/'
document.body.append(script)
});
</script>
</body>
</html>
app.js
const Koa = require('koa')
const app = new Koa()
app.use(async ctx => {
ctx.code = 401
ctx.body = `callback('hello world')`
})
app.listen(3000)
发现前端正常打印数据,浏览器并不会弹出登录框,如下
换用cors和xhr尝试一下
index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<button class="target">测试</button>
<script>
function get(url) {
return new Promise(function (fulfil, reject) {
var xhr = new XMLHttpRequest();
xhr.open('GET', url);
xhr.onload = function () {
fulfil(xhr.responseText);
};
xhr.onerror = reject;
xhr.send();
});
}
var target = document.querySelector('.target');
target.addEventListener('click', function () {
get('http://localhost:3000/')
.then(function (data) {
target.innerHTML = data;
});
});
</script>
</body>
</html>
app.js
const Koa = require('koa')
const app = new Koa()
app.use(async ctx => {
ctx.status = 401
ctx.set('Access-Control-Allow-Origin', '*');
ctx.set('Access-Control-Allow-Credentials', 'true');
ctx.body = `hello world`
})
app.listen(3000)
发现后台虽然返回了401,但是chrome并没有弹出要求登录的弹窗
综上,可以得出结论:
在通过jsonp和xhr或者接口json数据时,只返回401,chrome浏览器是不会主动弹出要求登录的弹窗的
在网络上查阅资料后知道,除了http状态码为401之外,后台还必须在请求头设置WWW-Authenticate响应头部,如下:
ctx.set("WWW-Authenticate", `Basic realm="oauth2/client"`)
可以看到浏览器会弹出登录弹窗,如下: