当前位置: 首页 > 知识库问答 >
问题:

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

商业
2023-03-14

在花了整整两天的时间搜索网络,阅读文档和大量面临同样问题的人的公开问题后,我仍然不明白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

我的十亿美元问题:

  • 我如何以及在哪里访问x-csrf-令牌,以及如何将其添加到我的请求中?
  • CookieXSRFStrategy('x-csrf-令牌','x-csrf-令牌');到底是做什么的?我不喜欢黑匣子的感觉/理解文档解释的方式。我可以访问它的数据吗?

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

>

  • 在我的情况下,它没有设置标题。。。但是为什么呢?

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

    请不要用像“document.cookie”这样的一句话回答。没有元数据的数据毫无用处

  • 共有2个答案

    邵诚
    2023-03-14

    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()
                ....    
    
    卫建义
    2023-03-14

    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”的头的访问都是被禁止的:

    禁止响应报头名称是一个报头名称,它是一个不区分字节大小写的匹配:

      设置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.cookieAPI只能访问加载文档时设置的cookie,而不能访问任何其他cookie。

    因此,您应该重新考虑服务器端的客户机/服务器通信流,因为您能够复制到标题中的唯一cookie是与您的脚本所运行的文档(index.html)一起发送的cookie。

    它不是一个http只有cookie,所以它应该可以通过js访问,即使它是X起源的

    httpOnly使cookie对文档不可用。cookieAPI,但正如我告诉你的,document。cookie指的是随文档一起发送的cookie,而不是通过Ajax响应发送的cookie。您可以在响应文档中使用Set Cookie头进行数千次ajax调用。cookie仍然是相同的字符串,没有任何修改。

    服务器应该只发送一个x-csrf-tokencookie,其中包含文档中的令牌,并且您应该使用该令牌,该令牌对于使用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令牌名称和值: