Angularjs $http 似乎不理解响应中的“Set-Cookie”
Posted
技术标签:
【中文标题】Angularjs $http 似乎不理解响应中的“Set-Cookie”【英文标题】:Angularjs $http does not seem to understand "Set-Cookie" in the response 【发布时间】:2013-10-23 09:08:14 【问题描述】:我有一个带有 Passport 模块的 nodejs express REST api 用于身份验证。 登录方法 (GET) 在标头中返回一个 cookie。当我从 Chrome 调用它时,它工作正常,我的 cookie 是在我的浏览器中设置的。
但是如果我通过 $http 从 Angularjs 调用它,cookie 没有设置。
Set-Cookie:connect.sid=s%3Ad7cZf3DSnz-IbLA_eNjQr-YR.R%2FytSJyd9cEhX%2BTBkmAQ6WFcEHAuPJjdXk3oq3YyFfI; Path=/; HttpOnly
如上所示,Set-Cookie 存在于 http 服务响应的标头中。
也许 HttpOnly 可能是这个问题的根源?如果是,我该如何更改?这是我的快速配置:
app.configure(function ()
app.use(allowCrossDomain);
app.use(express.bodyParser());
app.use(express.cookieParser())
app.use(express.session( secret: 'this is a secret' ));
app.use(flash());
//passport init
app.use(passport.initialize());
app.use(passport.session());
app.set('port', process.env.PORT || 8080);
);
感谢您的帮助
【问题讨论】:
您能否提供调用 $http 进行登录的 Angular 方法。暂时不知道怎么回事 【参考方案1】:确保将您的 $http 请求配置为使用凭据。 来自 XHR 文档:
https://developer.mozilla.org/en-US/docs/HTTP/Access_control_CORS
XMLHttpRequest 和 访问控制是发出“有凭证的”请求的能力,这些请求是 了解 HTTP Cookie 和 HTTP 身份验证信息。经过 默认情况下,在跨站点 XMLHttpRequest 调用中,浏览器不会 发送凭据。必须在 XMLHttpRequest 上设置一个特定的标志 对象被调用时。
你可以使用options对象来设置凭证的使用,见
http://docs.angularjs.org/api/ng.$http
例子:
$http(withCredentials: true, ...).get(...)
【讨论】:
但是 AngularJS 仍然无法理解响应中的set-cookie
。
我花了一天多的时间才意识到withCredentials = true
不仅告诉浏览器在请求时附加 cookie,而且还告诉它在响应时保存新的 cookie。这与 fetch
函数的 ajax 选项相同,其中必须应用 credentials: 'include'
以使浏览器根据请求和响应发送和设置 cookie。 IE。发送login
ajax 请求到专用api 时,虽然不需要cookie,但必须设置withCredentials=true
否则接收到的sessionid
cookie 将可用但浏览器不会保存它。【参考方案2】:
您如何检查 cookie 是否存在?
$http
只是浏览器 XHR 的包装,就像 jQuery 的 $.ajax
和朋友一样。这意味着您的浏览器将正常处理 cookie。
我的猜测是 cookie 正在设置,但您正试图通过 document.cookie
读取它。 HttpOnly
阻止脚本访问 cookie。 这是一件好事。
HttpOnly
有助于缓解 XSS 攻击。它使恶意脚本无法窃取用户的会话令牌(以及他们的登录)。 不要关闭HttpOnly
。
无论如何,您应该不需要 cookie。由于$http
只是 XHR 的一个包装器,因此浏览器会在您下次发出请求时自动发送 cookie。您可以通过查看开发者工具的网络面板中的请求来验证这一点。
【讨论】:
我会编辑帖子以解决将 withCredentials 设置为 true 的特定要求。没有它,它不会发送 cookie 以及 Access-Control-Allow-Credentials 标头。关于 HttpOnly 的 cmets,这是一个非常好的点 +1,可以确保一切都是安全的。【参考方案3】:我通过在角度 $http
请求中设置 withCredential : true
并通过设置解决了这个问题:
res.header("Access-Control-Allow-Credentials", true);
在我的快速服务器配置中。通过这样做,我的 cookie 会很好地出现在我的浏览器 cookie 列表中。
【讨论】:
【参考方案4】:以下解决方案对我有用
在 Angular 中,我使用了以下代码 sn-p
withCredentials: true
我的请求。
this._http.post(this._apiUrl + 'api/' + url, data, withCredentials: true )
.subscribe(data => resolve(data) , error => this.showServerError(error))
在 Node 中,在获得解决方案之前,我只是使用
初始化 CORSapp.use(cors());
但是,现在我已经实现了下面的代码sn-p
app.use(cors(origin: [
"http://localhost:5000"
], credentials: true))
http://localhost:5000 是我的 Angular 应用程序端点。你 可以从 config 或 .env 文件中动态设置这个 URL。
希望上述解决方案能解决您的问题。
【讨论】:
【参考方案5】:你可以通过配置express.session
来改变它:
app.use(express.session(
secret : 'this is a secret',
cookie :
httpOnly : false,
maxAge : XXX // see text
);
但我认为 Angular 不太关心 cookie,它们由浏览器处理(我同意 @josh3736 的观点,即您应该将 httpOnly
保留为 true
)。
这可能与您的 cookie 是(浏览器)会话 cookie 有关。您可以通过为 cookie 显式设置 maxAge
(以毫秒为单位)来尝试看看它是否效果更好。
【讨论】:
以上是关于Angularjs $http 似乎不理解响应中的“Set-Cookie”的主要内容,如果未能解决你的问题,请参考以下文章
405 方法不允许使用 $http 服务 AngularJS
AngularJS 2/4 中 BehaviourSubject 中的 HTTP 响应缓存和下一步