ng2从cookie获取csrf令牌将其作为标题发布

Vik*_*ode 7 cookies csrf angular

在花了整整两天的时间搜索网络并阅读文档和大量面临同样问题的人的开放性问题之后,我仍然不了解Angular 2如何处理(x-origin)cookie以及如何访问它们.

问题是: 后端发送了2个带有x-csrf-token和JSESSIONID的cookie.我的工作是将csrf令牌保留在内存中(ng2)并将其(仅)作为标题(不是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
Run Code Online (Sandbox Code Playgroud)

我的部分解决方案: 我创建了一个扩展BaseRequestOptions的自定义RequesstOptions类.添加了一些额外的标头,并将'withCredentials'设置为true.

export class MyRequestOptions extends BaseRequestOptions {

  headers: Headers = new Headers({
    'Accept': 'application/json',
    'Content-Type': 'application/json',
  });

  withCredentials = true;
}
Run Code Online (Sandbox Code Playgroud)

在我的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() );
  }
}
Run Code Online (Sandbox Code Playgroud)

在我的app.module中我做了这样的魔术:

 providers: [
    { provide: RequestOptions, useClass: DocumentumDefaultRequestOptions },
    { provide: XSRFStrategy, useFactory: xsrfFactory }
  ],
Run Code Online (Sandbox Code Playgroud)

我的xsrfFactory

export function xsrfFactory() {
  return new CookieXSRFStrategy('x-csrf-token', 'x-csrf-token');
}
Run Code Online (Sandbox Code Playgroud)

我的部分结果: 此时,角度会发送一个cookie,其中包含jsessionid和x-csrf-token等每个请求(GET和POST无歧视):

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
Run Code Online (Sandbox Code Playgroud)

我十亿美元的问题:

  • 我如何以及在何处访问x-csrf-token,以及如何将其添加到我的请求中?
  • 究竟做CookieXSRFStrategy('x-csrf-token', 'x-csrf-token');了什么.我不喜欢黑盒子感觉/理解文档解释它的方式.我可以访问数据吗?

在发送HTTP请求之前,CookieXSRFStrategy会查找名为XSRF-TOKEN的cookie,并使用该cookie的值设置名为X-XSRF-TOKEN的标头.

  • 它没有在我的情况下设置标题...但为什么?

  • 现在我正在使用sessionid和csrf令牌将cookie发送到后端,但发送的是什么?CookieXSRFStrategy或'withCredentials'标志.

请不要像"document.cookie"那样回答一个班轮.没有元数据,数据就毫无用处

n00*_*dl3 18

角度5.0+更新

Http服务beign不赞成使用HttpClient,CookieXSRFStrategy该类也已被弃用,现在这个任务被委托给了HttpClientXsrfModule班级.如果要自定义标题和cookie名称,只需要像这样导入此模块:

@NgModule({
  imports: [
    HttpClientModule,
    HttpClientXsrfModule.withConfig({
      cookieName: 'My-Xsrf-Cookie',
      headerName: 'My-Xsrf-Header',
    }),
  ]
})
export class MyModule{}
Run Code Online (Sandbox Code Playgroud)

对于未来的读者:

Ajax响应cookie

您无法从任何Ajax响应访问任何cookie,如果您检查XHR规范,您会注意到禁止访问与"Set-Cookie"匹配的标头:

禁止响应标头名称是标头名称,它是以下之一的字节大小写不匹配:

  • Set-Cookie
  • Set-Cookie2

但我的饼干不是 httpOnly

对你有好处,但httpOnly只说明你的cookie无法通过访问document.cookie(参见进一步的说明).

document.cookieAPI

你将是唯一的饼干能够使用JavaScript是访问document.cookie,但document.cookie指的是已经与文档发送的cookie和(你的脚本上运行的页面)将不会在任何时候得到修改.MDN明确指出它涉及当前的文件:

Document.cookie

获取并设置与当前文档关联的cookie.对于通用库,请参阅此简单的cookie框架.

资料来源:MDN

由Ajax响应设置的任何cookie都不属于当前文档.

那么我如何实现我的csrf保护呢?

标头令牌保护cookie是要走的路.请注意,您将在整个会话期间发送的令牌是相同的,并且不会根据发送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=/
    
    Run Code Online (Sandbox Code Playgroud)
  • 在客户端运行的JavaScript读取其值并将其复制到随每个事务请求一起发送的自定义HTTP头中

    X-Csrf-Token: i8XNjC4b8KVok4uw5RftR38Wgp2BFwql
    
    Run Code Online (Sandbox Code Playgroud)
  • 服务器验证令牌的存在和完整性

此技术的安全性基于以下假设:只有在同一来源中运行的JavaScript才能读取cookie的值.从流氓文件或电子邮件运行的JavaScript将无法读取它并复制到自定义标头中.即使csrf-token cookie将与恶意请求一起自动发送,服务器仍然期望有效的X-Csrf-Token标头.

来源:维基百科:CSRF

有了Angular 2+,这个任务就完成了CookieXSRFStrategy.

原始答案

我如何以及在何处访问x-csrf-token,以及如何将其添加到我的请求中?

使用CookieXSRFStrategy似乎是将其添加到您的请求的方式.对于"如何",不幸的是,答案可能是"你不能"(见进一步).

CookieXSRFStrategy是什么('x-csrf-token','x-csrf-token'); 确切地说.我不喜欢黑盒子感觉/理解文档解释它的方式.

CookieXSRFStrategy

/**
 * `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);
    }
  }
}
Run Code Online (Sandbox Code Playgroud)

资源

基本上,它从中读取cookie document.cookie并相应地修改Request标头.

现在我正在使用sessionid和csrf令牌将cookie发送到后端,但发送的是什么?CookieXSRFStrategy或'withCredentials'标志.

这是withCredentials标志,这个标志表示XHR应该发送所有已发送的cookie(即使是之前由Ajax响应设置的那些,但是作为cookie,而不是标题,并且没有办法改变这种行为)

它没有在我的情况下设置标题...但为什么?

您正在讨论的cookie不是与文档(index.html)一起发送的,而是与另一个ajax请求一起发送的.事实是你无法访问由ajax响应设置的cookie(请参阅此答案),因为这将是一个安全问题:www.stackoverflow.com从随机网页上获取简单的ajax 会获得堆栈溢出cookie,并且攻击者可以轻松窃取它(如果Access-Control-Allow-Origin: *stackoverflow响应中存在标头).

另一方面,document.cookieAPI只能访问加载文档时设置的cookie,而不能访问任何其他cookie.

因此,您应该重新考虑服务器端的客户端/服务器通信流,因为您将能够复制到标头的唯一cookie是与脚本运行的文档一起发送的cookie(索引). HTML).

它不是一个httpOnly cookie所以它应该可以用js访问,即使它是X原点

httpOnly使cookie不可用于document.cookieAPI,正如我所说,document.cookie指的是与文档一起发送cookie,而不是通过Ajax响应发送cookie.您可以Set-Cookie在响应中使用Header 进行数千次ajax调用,document.cookie仍然是相同的字符串,无需任何修改.

十亿美元的解决方案

服务器应该只发送一个x-csrf-token包含带有文档的令牌的cookie,并且您应该使用对每个请求使用的整个会话有效的令牌CookieXSRFStrategy.为什么?因为这就是它的工作原理.

  • 是的,现在是`HttpClientXsrfModule.withOptions({ cookieName : "foo", headerName : "bar"})`。我明天编辑。 (2认同)