javascript - XSRF - 如何设置跨域 cookie

标签 javascript spring http angular electron

我开发了 REST API 和两个 JavaScript 客户端(单页应用程序和原生应用程序 - 基于 Electron )。在两个客户端中,我的用户都通过 OAuth2 流进行身份验证:

  • 将用户密码发送到服务器
  • 获取 access_token(纯文本)和 refresh_token(httponly cookie)
  • 当 token 过期时,他们正在刷新它,向/refresh 端点发送请求(服务器从 cookie 中读取 refresh_token)

  • 现在我想实现csrf保护。所以我在后端(Spring)实现了它:
        @Override
        public void configure(HttpSecurity http) throws Exception {
            http.csrf().csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse()).and()
                    .authorizeRequests().antMatchers("/", "/index.html", "/token/**").permitAll()
                    .anyRequest().authenticated();
        }
    

    我的 SPA 运行良好, Angular 从 cookie 中读取 XSRF-TOKEN 并将其发送到 X-XSRF-TOKEN header 中。我遇到了 Electron 应用程序的问题。它无权访问 cookie(因为来源不同 - Electron 在 file:// url 上运行),因此无法设置 X-XSRF-TOKEN header 。

    我该如何处理这样的问题?有没有办法使“跨域”cookie 生效?或者,也许我可以通过 Electron 魔术 Electron API 以某种方式获取 cookie 值(如果它可以访问文件系统,也许它可以访问在机器上创建的任何 cookie)?

    最佳答案

    我遇到了同样的问题,并最终设法通过实现这样的 Angular http 拦截器来解决它:

    @Injectable()
    export class HttpXsrfInterceptor implements HttpInterceptor {
    
      constructor(private tokenExtractor: HttpXsrfTokenExtractor, //from angular
                  private nativeAuthService: NativeAuthService) { //my native service
      }
    
      intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
        //this works in web
        const headerName = 'X-XSRF-TOKEN';
        const token = this.tokenExtractor.getToken() as string;
        if (token !== null && !req.headers.has(headerName)) {
          req = req.clone({ headers: req.headers.set(headerName, token) });
          return next.handle(req);
        }
    
        //this works in electron
        return this.nativeAuthService.getCookieValue('XSRF-TOKEN').pipe(
          mergeMap((xsrfToken: string) => {
            if (xsrfToken && !req.headers.has(headerName)) {
              req = req.clone({ headers: req.headers.set(headerName, xsrfToken) });
            }
            return next.handle(req);
          }),
        );
      }
    }
    

    而我的nativeAuthService基本上只是在electron主进程中调用了这个方法:
    export function getCookieValue(cookieName: string): Observable<string> {
      return from(session.defaultSession.cookies.get({ name: cookieName })
        .then((cookies: Electron.Cookie[]) => {
          if (cookies.length == 1) {
            return cookies[0].value;
          } else {
            if (cookies.length > 1) {
              throw Error(`There is more than one cookie with the name: ${ cookieName }.`);
            }
            return '';
          }
        }));
    }
    

    关于javascript - XSRF - 如何设置跨域 cookie,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41840817/

    相关文章:

    php - 服务器为肯定存在于正确目录中的资源提供 410 错误

    c# - 弹出窗口拦截器验证

    hibernate - 在带有 jpa/hibernate 的 Spring 中,如何保持 session 打开以避免延迟初始化异常?

    java - apache httpclient 多次执行

    java - hibernate 异常 : Couldn't obtain transaction-synchronized Session for current thread

    java - 防止忘记在 Spring 中配置事务

    http - 使用 Content-Type 对 HTTP GET 的正确响应

    javascript - 使用 D3 有条件地附加名称集的元素

    javascript - 如何从 telerik Rad 电子表格中删除控件

    javascript - 选中复选框,自动更新复选框