CSRFGuard 3 Token Injection

本文介绍OWASP CSRF Guard 3的两种主要令牌注入策略:JavaScript DOM操作和JSP标签库。这两种方法帮助开发者保护Web应用免受跨站请求伪造攻击。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Overview

OWASP CSRFGuard implements a variant of the synchronizer token pattern to mitigate the risk of CSRF attacks. In order to implement this pattern, CSRFGuard must offer the capability to place the CSRF prevention token within the HTML produced by the protected web application. CSRFGuard 3 provides developers more fine grain control over the injection of the token. Developers can inject the token in their HTML using either dynamic JavaScript DOM manipulation or a JSP tag library. CSRFGuard no longer intercepts and modifies the HttpServletResponse object as was done in previous releases. The currently available token injection strategies are designed to make the integration of CSRFGuard more feasible and scalable within current enterprise web applications. Developers are encouraged to make use of both the JavaScript DOM Manipulation and the JSP tag library strategies for a complete token injection strategy. The JavaScript DOM Manipulation strategy is ideal as it is automated and requires minimal effort on behalf of the developer. In the event the JavaScript solution is insufficient within a particular application context, developers should leverage the JSP tag library. The purpose of this article is to describe the token injection strategies offered by OWASP CSRFGuard 3.

JavaScript DOM Manipulation

OWASP CSRFGuard 3 supports the ability to dynamically inject CSRF prevention tokens throughout the DOM currently loaded in the user's browser. This strategy is extremely valuable with regards to server-side performance as it simply requires the serving of a dynamic JavaScript file. There is little to no performance hit when the fetched dynamic JavaScript updates the browser's DOM. Making use of the JavaScript token injection solution requires the developer map a Servlet and place a JavaScript HTML tag within all pages sending requests to protected application resources. Developers are strongly encouraged to leverage the JavaScript token injection strategy by default. This strategy requires minimal effort on behalf of the developer as most of the token injection logic is automated. In the event that the JavaScript automated solution may be insufficient for a specific application context, developers should leverage the OWASP CSRFGuard JSP tag library.

Note: Use of JavaScript DOM Manipulation is required for Ajax support.

Declare and Configure JavaScriptServlet

The JavaScript file used for token injection is dynamically generated by the JavaScriptServlet class using a template file. Ensure that the Owasp.CsrfGuard.jar file is found within the target application's classpath. Copy the Owasp.CsrfGuard.js template file from the OWASP CSRFGuard distribution folder to a non-publicly accessible directory within the target application. For the remainder of this section, we assume the Owasp.CsrfGuard.js template file was placed in the application's WEB-INF folder. Edit the deployment descriptor (web.xml) to declare the JavaScriptServlet class along with any associated initialization parameters. Consider the following configuration snippet taken from theOwasp.CsrfGuard.Test application:

<servlet>
     <servlet-name>JavaScriptServlet</servlet-name>
     <servlet-class>org.owasp.csrfguard.servlet.JavaScriptServlet</servlet-class>
     <init-param>
         <param-name>source-file</param-name>
         <param-value>WEB-INF/Owasp.CsrfGuard.js</param-value>
     </init-param>
     <init-param>
         <param-name>inject-into-forms</param-name>
         <param-value>true</param-value>
     </init-param>
     <init-param>
         <param-name>inject-into-attributes</param-name>
         <param-value>true</param-value>
     </init-param>
    <init-param>
         <param-name>domain-strict</param-name>
         <param-value>false</param-value>
    </init-param>
    <init-param>
         <param-name>referer-pattern</param-name>
         <param-value>.*localhost.*</param-value>
    </init-param>
</servlet>

The aforementioned configuration snippet declares the JavaScriptServlet class using the name "JavaScriptServlet". JavaScriptServlet accepts various initialization parameters augmenting the behavior of the class at runtime. The provided configuration snippet instructs JavaScriptServlet to...

  1. Leverage the template JavaScript file at WEB-INF/Owasp.CsrfGuard.js
  2. Inject the token into all HTML forms
  3. Inject the token into all src and href attributes
  4. Leverage loose same origin matching criteria when placing the token in URL resources

Consider the following for a more detailed listing of the initialization parameters supported by JavaScriptServlet:

source-file

Denotes the location of the JavaScript template file that should be consumed and dynamically augmented by the JavaScriptServlet class. The default value is WEB-INF/Owasp.CsrfGuard.js. Use of this property and the existence of the specified template file is required.

domain-strict

Boolean value that determines whether or not the dynamic JavaScript code should be strict with regards to what links it should inject the CSRF prevention token. With a value of true, the JavaScript code will only place the token in links that point to the same exact domain from which the HTML originated. With a value of false, the JavaScript code will place the token in links that not only point to the same exact domain from which the HTML originated, but sub-domains as well.

referer-pattern

Allows the developer to specify a regular expression describing the required value of the Referer header. Any attempts to access the servlet with a Referer header that does not match the captured expression is discarded. Inclusion of referer header checking is to help minimize the risk of JavaScript Hijacking attacks that attempt to steal tokens from the dynamically generated JavaScript. While the primary defenses against JavaScript Hijacking attacks are implemented within the dynamic JavaScript itself, referer header checking is implemented to achieve defense in depth.

cache-control

Allows the developer to specify the value of the Cache-Control header in the HTTP response when serving the dynamic JavaScript file. The default value is private, maxage=28800. Caching of the dynamic JavaScript file is intended to minimize traffic and improve performance. Note that the Cache-Control header is always set to "no-store" when either the "Rotate" "TokenPerPage" options is set to true in Owasp.CsrfGuard.properties.

inject-into-forms

Boolean value that determines whether or not the dynamic JavaScript code should inject the CSRF prevention token as a hidden field into HTML forms. The default value is true. Developers are strongly discouraged from disabling this property as most server-side state changing actions are triggered via a POST request.

inject-into-attributes

Boolean value that determines whether or not the dynamic JavaScript code should inject the CSRF prevention token in the query string of src and href attributes. Injecting the CSRF prevention token in a URL resource increases its general risk of exposure to unauthorized parties. However, most JavaEE web applications respond in the exact same manner to HTTP requests and their associated parameters regardless of the HTTP method. The risk associated with not protecting GET requests in this situation is perceived greater than the risk of exposing the token in protected GET requests. As a result, the default value of this attribute is set to true. Developers that are confident their server-side state changing controllers will only respond to POST requests (i.e. discarding GET requests) are strongly encouraged to disable this property.

Map JavaScriptServlet

Developers must map the JavaScriptServlet to a URI space such that the Servlet class can be remotely accessed by the dynamic JavaScript code. Consider the following configuration snippet taken directly from the [hhttps://github.com/esheri3/OWASP-CSRFGuard/tree/master/Owasp.CsrfGuard.Test Owasp.CsrfGuard.Test] application:

<servlet-mapping>
     <servlet-name>JavaScriptServlet</servlet-name>
     <url-pattern>/JavaScriptServlet</url-pattern>
</servlet-mapping>

The aforementioned configuration snippet maps the Servlet referenced by the name "JavaScriptServlet" to the URI space "/JavaScriptServlet". Any request sent to the /JavaScriptServlet URI will produce a dynamically generated CSRFGuard JavaScript file specific to the user's current session.

Inject Dynamic JavaScript

Developers are required to place an HTML script tag within all pages that are known to send requests to CSRF protected resources. All requests within the current HTML page are augmented to ensure they submit the correct CSRF token for the user's current session. Note that inclusion of the dynamic JavaScript does not protect the current page. Rather, the script ensures the CSRF token is transmitted within all requests generated by the current page. Consider the following code snippet taken directly from the Owasp.CsrfGuard.Test application:

<script src="/Owasp.CsrfGuard.Test/JavaScriptServlet"></script>

The script tag retrieves and executes the dynamically generated JavaScript from the Servlet mapped at /Owasp.CsrfGuard.Test/JavaScriptServlet. This JavaScript code will register an event handler with window.onload. Once triggered, the code will iterate over every HTML element within the DOM looking for either form tags and or tags containing href or src attributes as configured by the JavaScriptServlet initialization parameters. Forms are dynamically updated to include the CSRFGuard token via a hidden field and tags using src and href attributes are updated to include the CSRFGuard token via a query string parameter.

JSP Tag Library

OWASP CSRFGuard 3 exposes a JSP tag library providing developers more fine grain control over token injection. The library exposes JSP tags that allow access to the token name, the token value, and the token name value pair delimited by an equals (=) sign. In order to make use of the tag library, ensure the Owasp.CsrfGuard.jar file is found within the target application's classpath. For example, the Owasp.CsrfGuard.Test application places the OWASP CSRFGuard jar file within the WebContent/WEB-INF/lib directory. After placing the library in the classpath, developers can reference the tags in JSP pages using predefined URI reference. The following JSP code snippet imports the tag library and makes it available using the prefix "csrf":

<%@ taglib uri="http://www.owasp.org/index.php/Category:OWASP_CSRFGuard_Project/Owasp.CsrfGuard.tld" prefix="csrf" %>

The benefit of using the JSP tag library to inject the CSRF prevention token is the fine grain level of control. Developers can place the token in all the correct locations within the context of their applications. This strategy is useful in application contexts where the JavaScript DOM Manipulation strategy is insufficient.

Display Token Name

The OWASP CSRFGuard token name can be obtained through the token-name tag. The token-name tag is useful when injecting the CSRFGuard token name in a non-query string context. Consider the following code snippet taken from theOwasp.CsrfGuard.Test application. This code makes use of the token-name tag to reference the token name in the name attribute of a hidden input field:

<form name="test1" action="protect.html">
     <input type="text" name="text" value="text"/>
     <input type="submit" name="submit" value="submit"/>
     <input type="hidden" name="<csrf:token-name/>" value="<csrf:token-value/>"/>
</form>

Display Token Value

The OWASP CSRFGuard token value can be obtained through the token-value tag. The token-value tag is useful when injecting the CSRFGuard token value in a non-query string context. Consider the following code snippet taken from theOwasp.CsrfGuard.Test application. This code makes use of the token-value tag to reference the token value in the value attribute of a hidden input field:

<form name="test1" action="protect.html">
     <input type="text" name="text" value="text"/>
     <input type="submit" name="submit" value="submit"/>
     <input type="hidden" name="<csrf:token-name/>" value="<csrf:token-value/>"/>
</form>

The token value tag must be used in conjunction with the URI attribute when using the unique token per page model (org.owasp.csrfguard.TokenPerPage). The value of the uri attribute is the URI for which the token value will be posted. Consider the following example which sets the URI to the destination of the form, "protect.html":

<form id="formTest1" name="formTest1" action="protect.html">
     <input type="text" name="text" value="text"/>
     <input type="submit" name="submit" value="submit"/>
     <input type="hidden" name="<csrf:token-name/>" value="<csrf:token-value uri="protect.html"/>"/>
</form>

Display Token Name Value Pair

The OWASP CSRFGuard token name value pair, delimited by an equals sign (=), can be obtained though the token tag. The token tag is useful when injecting the CSRFGuard token value in a query string context. Consider the following code snippet taken from the Owasp.CsrfGuard.Test application. This code makes use of the token tag to reference the token name value pair in the href attribute of an anchor tag:

<a href="protect.html?<csrf:token/>">protect.html</a>

The token name value pair tag must be used in conjunction with the URI attribute when using the unique token per page model (org.owasp.csrfguard.TokenPerPage). The value of the uri attribute is the URI for which the token value will be posted. Consider the following example which sets the URI to the destination of the link, "protect.html":

<a href="protect.html?<csrf:token uri="protect.html"/>">protect.html</a>

Generate Form with Prevention Token

The OWASP CSRFGuard JSP library implements a tag library designed specifically to generate HTML forms with the CSRF prevention token automatically embedded as a hidden field. This strategy simplifies the integration of the CSRF token, especially when using the unique token per page model (org.owasp.csrfguard.TokenPerPage). The tag accepts dynamic attribute name value pairs and simply outputs them to the page. As a result, you are free to use the same attribute values made available in a standard HTML form. There is no special output encoding performed on these dynamic attributes. Take care to perform the appropriate validation and output encoding for all dynamic attributes used in conjunction with untrusted data. Consider the following code snippet which will produce a HTML form with an embedded CSRF token. No special care must be taken when using this flag in conjunction with the unique token per uri model:

<csrf:form id="formTest2" name="formTest2" action="protect.html">
     <input type="text" name="text" value="text"/>
     <input type="submit" name="submit" value="submit"/>
</csrf:form>

Generate Link with Prevention Token

The OWASP CSRFGuard JSP library implements a tag library designed specifically to generate HTML anchor tags with the CSRF prevention token automatically embedded as a query string parameter. This strategy simplifies the integration of the CSRF token, especially when using the unique token per page model (org.owasp.csrfguard.TokenPerPage). The tag accepts dynamic attribute name value pairs and simply outputs them to the page. As a result, you are free to use the same attribute values made available in a standard HTML anchor. There is no special output encoding performed on these dynamic attributes. Take care to perform the appropriate validation and output encoding for all dynamic attributes used in conjunction with untrusted data. Consider the following code snippet which will produce a HTML anchor tag with an embedded CSRF token. No special care must be taken when using this flag in conjunction with the unique token per uri model:

<csrf:a href="protect.html">protect.html</csrf:a>
### Vue3 中手动刷新 Token 的实现方法 在 Vue3 应用中,可以通过拦截器机制来处理 API 请求中的 `access_token` 和 `refresh_token` 刷新逻辑。以下是具体实现方式: #### 1. 安装依赖库 为了简化 JWT 解析和生成的过程,可以安装 `js-cookie` 来管理 Cookie 存储以及 `axios` 进行 HTTP 请求。 ```bash npm install axios js-cookie ``` --- #### 2. 创建 Axios 配置文件 创建一个名为 `api.js` 的配置文件,用于设置全局的请求拦截器和响应拦截器。 ```javascript // api.js import axios from &#39;axios&#39;; import Cookies from &#39;js-cookie&#39;; const instance = axios.create({ baseURL: &#39;https://your-api-endpoint.com/api&#39;, // 替换为实际接口地址 timeout: 5000, }); // 请求拦截器 instance.interceptors.request.use( (config) => { const accessToken = Cookies.get(&#39;access_token&#39;); if (accessToken) { config.headers.Authorization = `Bearer ${accessToken}`; } return config; }, (error) => Promise.reject(error) ); // 响应拦截器 instance.interceptors.response.use( (response) => response.data, // 自定义返回数据结构 async (error) => { const originalRequest = error.config; // 如果状态码为401,则尝试刷新Token if (error.response.status === 401 && !originalRequest._retry) { originalRequest._retry = true; try { const refreshToken = Cookies.get(&#39;refresh_token&#39;); // 获取 refresh_token if (!refreshToken) throw new Error(&#39;Refresh token not found&#39;); // 调用后端接口获取新 token const res = await axios.post(&#39;/auth/refresh-token&#39;, { refresh_token: refreshToken }); const { access_token } = res.data; // 更新 access_token 并重新发送原请求 Cookies.set(&#39;access_token&#39;, access_token); instance.defaults.headers.common[&#39;Authorization&#39;] = `Bearer ${access_token}`; return instance(originalRequest); } catch (err) { console.error(&#39;Failed to refresh token:&#39;, err.message); Cookies.remove(&#39;access_token&#39;); Cookies.remove(&#39;refresh_token&#39;); window.location.href = &#39;/login&#39;; // 跳转至登录页 } } return Promise.reject(error); } ); export default instance; ``` 上述代码实现了以下功能: - **请求拦截器**:在每次发起请求前检查是否存在有效的 `access_token`,并将其加入请求头。 - **响应拦截器**:当服务器返回的状态码为 `401 Unauthorized` 时,触发 `refresh_token` 流程以更新 `access_token`[^3]。 --- #### 3. 后端服务支持 Refresh Token 功能 假设后端提供了一个 `/auth/refresh-token` 接口,该接口接收用户的 `refresh_token` 参数,并返回一个新的 `access_token` 及其有效期。例如,在 Java Spring Boot 中可参考如下实现[^2]: ```java @RestController @RequestMapping("/auth") public class AuthController { @Autowired private TokenService tokenService; @PostMapping("/refresh-token") public ResponseEntity<Map<String, Object>> refreshToken(@RequestBody Map<String, String> body) { String refreshToken = body.get("refresh_token"); User user = validateRefreshToken(refreshToken); // 校验 refresh_token 是否合法 if (user != null) { String newAccessToken = tokenService.getToken(user); // 使用相同的算法签发新的 access_token Map<String, Object> result = new HashMap<>(); result.put("access_token", newAccessToken); return ResponseEntity.ok(result); } else { return ResponseEntity.status(HttpStatus.UNAUTHORIZED).body(null); } } private User validateRefreshToken(String refreshToken) { // TODO: 实现 refresh_token 校验逻辑 return null; } } ``` 此部分需由后端开发人员完成,确保能够安全可靠地验证 `refresh_token` 并颁发新的 `access_token`。 --- #### 4. 登录成功后的 Token 存储 在用户登录成功后,将 `access_token` 和 `refresh_token` 存入浏览器的 Cookie 中以便后续使用。 ```javascript // login.vue async function handleLogin(credentials) { try { const response = await api.post(&#39;/auth/login&#39;, credentials); const { access_token, refresh_token } = response.data; // 将 tokens 存储到 cookie Cookies.set(&#39;access_token&#39;, access_token, { expires: 1 / 24 }); // 设置存活时间为 1 小时 Cookies.set(&#39;refresh_token&#39;, refresh_token, { expires: 7 }); // 设置存活时间为 7 天 alert(&#39;登录成功!&#39;); } catch (error) { console.error(&#39;登录失败:&#39;, error.message); } } ``` 此处需要注意的是,`access_token` 的生存周期较短(如 1 小时),而 `refresh_token` 的生存周期较长(如 7 天)。 --- ### 总结 以上展示了如何在 Vue3 中通过 Axios 拦截器实现手动刷新 Token 的功能。核心在于利用 `refresh_token` 在 `access_token` 过期的情况下向后端申请新的令牌,并动态替换原有请求头中的认证信息。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值