在花了整整两天的时间搜索网络,阅读文档和大量面临同样问题的人的公开问题后,我仍然不明白Angular 2是如何处理(x原点)cookie以及如何访问它们的。
问题:后端使用x-csrf-token发送2个cookie
HTTP/1.1 200 OK
Server: Apache-Coyote/1.1
Access-Control-Allow-Origin: http://localhost:4200
Access-Control-Allow-Credentials: true
Access-Control-Expose-Headers: Access-Control-Allow-Origin,Access-Control-Allow-Credentials
Set-Cookie: x-csrf-token=8555257a-396f-43ac-8587-c6d489e76026; Path=/app
Set-Cookie: JSESSIONID=73E38392C60370E38FBAF80143ECE212; Path=/app/; HttpOnly
Expires: Thu, 12 Apr 2018 07:49:02 GMT
Cache-Control: max-age=31536000
Content-Type: application/json;charset=UTF-8
Transfer-Encoding: chunked
Date: Wed, 12 Apr 2017 07:49:02 GMT
我的部分解决方案是:我创建了一个自定义RequestOptions类,它扩展了Base刚需选项。添加了一些额外的标题,并将“带凭据”设置为true。
export class MyRequestOptions extends BaseRequestOptions {
headers: Headers = new Headers({
'Accept': 'application/json',
'Content-Type': 'application/json',
});
withCredentials = true;
}
在我的HttpService中,我做了这篇文章,结果如下:
@Injectable()
export class HttpService {
constructor(
protected _http: Http,
protected requestOptions: RequestOptions
) { }
get(url): Observable<any> {
return this._http.get(url, this.requestOptions).map( res => res.json() );
}
post(url: string, object: any): Observable<any> {
return this._http.post(url, object, this.requestOptions).map( res => res.json() );
}
}
在我的应用程序中。模块i的神奇之处如下:
providers: [
{ provide: RequestOptions, useClass: DocumentumDefaultRequestOptions },
{ provide: XSRFStrategy, useFactory: xsrfFactory }
],
我的工厂
export function xsrfFactory() {
return new CookieXSRFStrategy('x-csrf-token', 'x-csrf-token');
}
我的部分结果是:此时angular发送一个cookie,其中包含每个请求(不加区分地获取和发布),带有jsessionid和x-csrf-token,如下所示:
POST /app/business-objects/business-objects-type HTTP/1.1
Host: localhost:8040
Connection: keep-alive
Content-Length: 26
Pragma: no-cache
Cache-Control: no-cache
Authorization: Basic ZG1hZG1pbjphZG1pbg==
Origin: http://localhost:4200
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/57.0.2987.133 Safari/537.36
Content-Type: application/json
Accept: application/json
Referer: http://localhost:4200/page
Cookie: JSESSIONID=B874C9A170EFC12BEB0EDD4266896F2A; x-csrf-token=0717876e-f402-4a1c-a31a-2d60e48509d3
我的十亿美元问题:
在发送HTTP请求之前,CookieXSRFStrategy会查找名为XSRF-TOKEN的cookie,并使用该cookie的值设置名为X-XSRF-TOKEN的标头。
>
在我的情况下,它没有设置标题。。。但是为什么呢?
现在,我正在用sessionid和csrf令牌将cookie发送到后端,但发送它的是什么?CookieXSRFStrategy或“withCredentials”标志。
请不要用像“document.cookie”这样的一句话回答。没有元数据的数据毫无用处
Angular内置了对XSRF的支持,请参见此处:https://angular.io/guide/http#security-xsrf-protection
"执行HTTP请求时,默认情况下,拦截器从cookie中读取令牌XSRF-TOKEN,并将其设置为HTTP标头X-XSRF-TOKEN"
因此,如果您的服务器设置了一个名为XSRF-TOKEN的cookie,那么它将自动工作!在客户端没有什么可做的。如果您想将cookie/头命名为其他名称,那么您也可以这样做:
imports: [
HttpClientModule,
HttpClientXsrfModule.withConfig({
cookieName: 'My-Xsrf-Cookie',
headerName: 'My-Xsrf-Header',
}),
]
如果您使用的是Spring安全,它支持角命名约定,因此您可以配置此服务器端:
@Configuration
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.csrf().csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse())
.and()
.authorizeRequests()
....
Http
服务beign已被弃用,支持HttpClient
,CookieXSRFStrategy类也已被弃用,现在这个任务被委托给HttpClientXsrfModule
类。如果你想自定义标题和cookie名称,你只需要像这样导入这个模块:
@NgModule({
imports: [
HttpClientModule,
HttpClientXsrfModule.withOptions({
cookieName: 'My-Xsrf-Cookie',
headerName: 'My-Xsrf-Header',
}),
]
})
export class MyModule{}
您无法从任何Ajax响应中访问任何cookie,如果您检查XHR规范,您将注意到任何对匹配“Set cookie”的头的访问都是被禁止的:
禁止响应报头名称是一个报头名称,它是一个不区分字节大小写的匹配:
Set-Cookie2
很好,但是http
只声明不能通过document.cookie
访问cookie(请参阅更多内容)。
您可以使用javascript访问的唯一cookie是document.cookie
但是document.cookie
指的是随文档一起发送的cookie(您的脚本运行的页面)不会在任何时候被修改。MDN明确指出,它指的是目前的文件:
获取并设置与当前文档关联的Cookie。有关通用库,请参见此简单cookie框架。
来源: MDN
Ajax响应设置的任何cookie都不属于当前文档。
cookie-to-header令牌保护是一条出路。请注意,您将在整个会话期间发送的令牌是相同的,并且不支持根据发送cookie的野生Ajax请求进行更改。
大多数操作都使用JavaScript的Web应用程序可能会使用依赖于同源策略的反CSRF技术:
>
在登录时,Web应用程序设置一个cookie,其中包含在整个用户会话中保持相同的随机令牌
Set-Cookie: Csrf-token=i8XNjC4b8KVok4uw5RftR38Wgp2BFwql; expires=Thu, 23-Jul-2015 10:25:33 GMT; Max-Age=31449600; Path=/
>
X-Csrf-Token: i8XNjC4b8KVok4uw5RftR38Wgp2BFwql
服务器验证令牌的存在性和完整性
这种技术的安全性基于这样一个假设,即只有在同一源代码中运行的JavaScript才能读取cookie的值。从恶意文件或电子邮件运行的JavaScript将无法读取它并复制到自定义头中。即使csrf令牌cookie将与恶意请求一起自动发送,服务器仍将需要有效的X-csrf-token头。
资料来源:维基百科:CSRF
使用Angular 2,该任务由CookieXSRFStrategy
类完成。
我如何以及在哪里访问x-csrf-令牌,以及如何将其添加到我的请求中?
使用CookieXSRFStrategy
似乎是将其添加到请求中的方法。不幸的是,对于“如何”的问题,答案可能是“你不能”(见下文)。
CookieXSRFStrategy('x-csrf-令牌','x-csrf-令牌');确切地做什么。我不喜欢黑匣子的感觉/理解文档解释的方式。
/**
* `XSRFConfiguration` sets up Cross Site Request Forgery (XSRF) protection for the application
* using a cookie. See https://www.owasp.org/index.php/Cross-Site_Request_Forgery_(CSRF)
* for more information on XSRF.
*
* Applications can configure custom cookie and header names by binding an instance of this class
* with different `cookieName` and `headerName` values. See the main HTTP documentation for more
* details.
*
* @experimental
*/
export class CookieXSRFStrategy implements XSRFStrategy {
constructor(
private _cookieName: string = 'XSRF-TOKEN', private _headerName: string = 'X-XSRF-TOKEN') {}
configureRequest(req: Request): void {
const xsrfToken = getDOM().getCookie(this._cookieName);
if (xsrfToken) {
req.headers.set(this._headerName, xsrfToken);
}
}
}
来源
基本上,它从document.cookie
读取cookie,并相应地修改请求
标头。
现在,我正在用sessionid和csrf令牌将cookie发送到后端,但发送它的是什么?CookieXSRFStrategy或“withCredentials”标志。
这是with credentials
标志,该标志指示XHR应发送所有已发送的cookie(即使是以前由Ajax响应设置的cookie,但作为cookie,而不是标头,并且无法更改此行为)
在我的情况下,它没有设置标题。。。但是为什么呢?
您正在谈论的cookie不是与文档(index.html
)一起发送的,而是来自另一个ajax请求。事实上,您无法访问ajax响应设置的Cookie(参见此答案),因为这将是一个安全问题:一个简单的ajax访问www.stackoverflow。来自随机网页的com
将获得堆栈溢出cookie,攻击者可以轻松窃取它(如果访问控制允许源代码:
标题出现在stackoverflow响应上)。
另一方面,document.cookie
API只能访问加载文档时设置的cookie,而不能访问任何其他cookie。
因此,您应该重新考虑服务器端的客户机/服务器通信流,因为您能够复制到标题中的唯一cookie是与您的脚本所运行的文档(index.html)一起发送的cookie。
它不是一个http只有cookie,所以它应该可以通过js访问,即使它是X起源的
httpOnly
使cookie对文档不可用。cookie
API,但正如我告诉你的,document。cookie
指的是随文档一起发送的cookie,而不是通过Ajax响应发送的cookie。您可以在响应文档中使用
仍然是相同的字符串,没有任何修改。Set Cookie
头进行数千次ajax调用。cookie
服务器应该只发送一个x-csrf-token
cookie,其中包含文档中的令牌,并且您应该使用该令牌,该令牌对于使用CookieXSRFStrategy
的每个请求在整个会话中都有效。为什么?因为这就是它的工作原理。
我对CakePHP(v3.7)比较陌生。我有一个应用程序,其中出现了“缺少Csrf令牌Cookie”错误。 在pplication.php,我有: 表单页面有一个隐藏的表单元素,其中包含_csrfToken。我不明白为什么没有在邮件上找到它? 深入研究后,我发现在CsrfProttionMiddleware.php中,下面的_validateToken()函数的行为如下: $cookie为空(没有
用于初始化会话的Web API方法正在成功返回cookie。前端是angular的,所以我调用cookie XSRF-TOKEN,因为angular说它将接受该值,并在所有后续请求中将其转换为名为X-XSRF-TOKEN的头。 作为参考,创建cookie的WebAPI获取控制器方法如下 使用Fiddler,我可以在响应中看到cookie。现在我期待两件事 对同一域的所有后续API调用应在请求头中包
我正在AngularJS SPA中使用资源所有者密码凭证OAuth 2.0流。有几篇文章(这里,这里…)这个问题的答案解释了我们不应该将刷新令牌存储在(web)客户端(LocalStorage)上,而是将它们加密存储在HttpOnly Cookie中,并使用代理API实现对refreh令牌的解密,从而将其转发给安全令牌服务。 大多数文章都暗示我们应该使用一种常见的保护机制来关注CSRF。我想知道单
我想从Stormpath帖子中对JWT令牌和CSRF提出疑问,这些令牌和CSRF解释了将JWT存储在localStorage或Cookie中的优缺点。 [...] 如果您使用JS从cookie中读取值,这意味着您不能在cookie上设置Httponly标志,因此现在站点上的任何JS都可以读取它,从而使其与在localStorage中存储内容的安全级别完全相同。 我试图理解为什么他们建议将xsrfT
我目前正在构建一个web应用程序,其后端完全构建在API Gateway/lambda中。我构建了一个自定义的JSON Web令牌(JWT)授权器来授权用户。目前我正在头字段中传递令牌。 不幸的是,我只能定义一个头字段,将令牌发送到API网关。我的应用程序将令牌存储在一个cookie中。 有什么办法吗?谢谢!
问题内容: 我在网站上启用了CSRF保护,但是CSRF令牌唯一一次放置在隐藏字段中的时间是何时使用。我正在通过ajax发布数据,并且也需要发送CSRF以防止出现500个错误。 我以为有一种方法可以将CSRF令牌显式地嵌入到页面中,但是我似乎找不到它。 如果页面上没有表单,如何获得CSRF令牌? 问题答案: 您可以通过安全性类获取CSRF令牌名称和值: