转-OWASP CSRFGuard使用细节
跨站请求伪造之开源项目CSRFGuard框架解决之道
什么是CSRF?
摘自【CSRF百度百科】
注意:原理性的东西自行搜索。
原理
当前防御 CSRF 的几种策略
在业界目前防御 CSRF 攻击主要有三种策略:
- 验证 HTTP Referer 字段;
- 在请求地址中添加 token 并验证;
- 在 HTTP 头中自定义属性并验证。
下面就分别对这三种策略进行详细介绍。
验证 HTTP Referer 字段
根据 HTTP 协议,在 HTTP 头中有一个字段叫 Referer,它记录了该 HTTP 请求的来源地址。在通常情况下,访问一个安全受限页面的请求来自于同一个网站,比如需要访问 http://bank.example/withdraw?account=bob&amount=1000000&for=Mallory,用户必须先登陆 bank.example,然后通过点击页面上的按钮来触发转账事件。这时,该转帐请求的 Referer 值就会是转账按钮所在的页面的 URL,通常是以 bank.example 域名开头的地址。而如果黑客要对银行网站实施 CSRF 攻击,他只能在他自己的网站构造请求,当用户通过黑客的网站发送请求到银行时,该请求的 Referer 是指向黑客自己的网站。因此,要防御 CSRF 攻击,银行网站只需要对于每一个转账请求验证其 Referer 值,如果是以 bank.example 开头的域名,则说明该请求是来自银行网站自己的请求,是合法的。如果 Referer 是其他网站的话,则有可能是黑客的 CSRF 攻击,拒绝该请求。
这种方法的显而易见的好处就是简单易行
,网站的普通开发人员不需要操心 CSRF 的漏洞,只需要在最后给所有安全敏感的请求统一增加一个拦截器来检查 Referer 的值就可以。特别是对于当前现有的系统,不需要改变当前系统的任何已有代码和逻辑,没有风险,非常便捷。
然而,这种方法并非万无一失。 Referer 的值是由浏览器提供的,虽然 HTTP 协议上有明确的要求,但是每个浏览器对于 Referer 的具体实现可能有差别,并不能保证浏览器自身没有安全漏洞。使用验证 Referer 值的方法,就是把安全性都依赖于第三方(即浏览器)来保障,从理论上来讲,这样并不安全。事实上,对于某些浏览器,比如 IE6 或 FF2,目前已经有一些方法可以篡改 Referer 值。 如果 bank.example 网站支持 IE6 浏览器,黑客完全可以把用户浏览器的 Referer 值设为以 bank.example 域名开头的地址,这样就可以通过验证,从而进行 CSRF 攻击。
即便是使用最新的浏览器,黑客无法篡改 Referer 值,这种方法仍然有问题。因为 Referer 值会记录下用户的访问来源,有些用户认为这样会侵犯到他们自己的隐私权,特别是有些组织担心 Referer 值会把组织内网中的某些信息泄露到外网中。因此,用户自己可以设置浏览器使其在发送请求时不再提供 Referer。 当他们正常访问银行网站时,网站会因为请求没有 Referer 值而认为是 CSRF 攻击,拒绝合法用户的访问。
在请求地址中添加 token 并验证
CSRF 攻击之所以能够成功,是因为黑客可以完全伪造用户的请求,该请求中所有的用户验证信息都是存在于 cookie 中,因此黑客可以在不知道这些验证信息的情况下直接利用用户自己的 cookie 来通过安全验证。要抵御 CSRF,关键在于在请求中放入黑客所不能伪造的信息,并且该信息不存在于 cookie 之中。 可以在 HTTP 请求中以参数的形式加入一个随机产生的 token,并在服务器端建立一个拦截器来验证这个 token,如果请求中没有 token 或者 token 内容不正确,则认为可能是 CSRF 攻击而拒绝该请求。
这种方法要比检查 Referer 要安全一些,token 可以在用户登陆后产生并放于 session 之中,然后在每次请求时把 token 从 session 中拿出,与请求中的 token 进行比对,但这种方法的难点在于如何把 token 以参数的形式加入请求。对于 GET 请求,token 将附在请求地址之后,这样 URL 就变成 http://url?csrftoken=tokenvalue。 而对于 POST 请求来说,要在 form 的最后加上 ,这样就把 token 以参数的形式加入请求了。但是,在一个网站中,可以接受请求的地方非常多,要对于每一个请求都加上 token 是很麻烦的,并且很容易漏掉, 通常使用的方法就是在每次页面加载时,使用 javascript 遍历整个 dom 树,对于 dom 中所有的 a 和 form 标签后加入 token。这样可以解决大部分的请求,但是对于在页面加载之后动态生成的 html 代码,这种方法就没有作用,还需要程序员在编码时手动添加 token。
该方法还有一个缺点是难以保证 token 本身的安全。特别是在一些论坛之类支持用户自己发表内容的网站,黑客可以在上面发布自己个人网站的地址。由于系统也会在这个地址后面加上 token,黑客可以在自己的网站上得到这个 token,并马上就可以发动 CSRF 攻击。为了避免这一点,系统可以在添加 token 的时候增加一个判断,如果这个链接是链到自己本站的,就在后面添加 token,如果是通向外网则不加。不过,即使这个 csrftoken 不以参数的形式附加在请求之中,黑客的网站也同样可以通过 Referer 来得到这个 token 值以发动 CSRF 攻击。这也是一些用户喜欢手动关闭浏览器 Referer 功能的原因。
在 HTTP 头中自定义属性并验证
这种方法也是使用 token 并进行验证,和上一种方法不同的是,这里并不是把 token 以参数的形式置于 HTTP 请求之中,而是把它放到 HTTP 头中自定义的属性里。通过 XMLHttpRequest 这个类,可以一次性给所有该类请求加上 csrftoken 这个 HTTP 头属性,并把 token 值放入其中。这样解决了上种方法在请求中加入 token 的不便,同时,通过 XMLHttpRequest 请求的地址不会被记录到浏览器的地址栏,也不用担心 token 会透过 Referer 泄露到其他网站中去。
然而这种方法的局限性非常大。XMLHttpRequest 请求通常用于 Ajax 方法中对于页面局部的异步刷新,并非所有的请求都适合用这个类来发起,而且通过该类请求得到的页面不能被浏览器所记录下,从而进行前进,后退,刷新,收藏等操作,给用户带来不便。 另外,对于没有进行 CSRF 防护的遗留系统来说,要采用这种方法来进行防护,要把所有请求都改为 XMLHttpRequest 请求,这样几乎是要重写整个网站,这代价无疑是不能接受的。
开源项目 CSRFGuard
简介
OWASP CSRFGuard是一个库,它实现同步器令牌模式的变体,以降低跨站点请求伪造(CSRF)攻击的风险。OWASP CSRFGuard库通过使用JavaEE过滤器进行集成,并公开了各种自动和手动方式,以将每会话或伪每请求令牌集成到HTML中。当用户与此HTML交互时,将使用相应的HTTP请求提交CSRF预防令牌(即加密随机同步器令牌)。OWASP CSRFGuard负责确保令牌存在且对当前HTTP请求有效。在没有正确的相应令牌的情况下向受保护资源提交请求的任何尝试都被视为正在进行的CSRF攻击并被丢弃。在放弃请求之前,可以将CSRFGuard配置为执行一个或多个操作,例如记录请求的各个方面以及将用户重定向到登录页面。最新版本增强了此策略,以支持使用Ajax提交的HTTP请求的可选验证以及referrer标头的可选验证。
OWASP-CSRFGuard 官网
github 项目地址
疑问?上面有介绍三种方式解决CSRF的攻击策略。为什么还要介绍CSRFGuard项目?
- 对于没有进行 CSRF 防护的遗留系统来说,以上方式无疑是致命的;CSRFGuard可以很好的解决这个问题。
- 三种策略都需自己实现,性能以及安全性并不高; CSRFGuard提供实现,直接配置即可。
- 控制粒度更具优势。可以设置不受保护的页面及URL请求。
测试项目
- 确保安装了
Apache Maven 3.0.4
或更高版本; - 确保安装了GPG并使用密钥生成密钥;
- 在本地克隆此存储库;
- 首先建立
csrfguard
项目,cd csrfguard
然后是mvn clean install;
- 随后构建并运行
csrfguard-test
项目;cd ../csrfguard-test
启动:mvn clean package tomcat7:run
; - 使用Web浏览器访问http://localhost:8000以打开测试项目的主页。
注:把测试项目代码看一遍就行。或者源码看一下,东西并不多,有兴趣可以稍微看看源码就能接上项目的。
安装
- 将Owasp.CsrfGuard.jar文件复制到应用程序的类路径中
- 在应用程序的部署描述符(web.xml)中声明CsrfGuard
- 根据需要配置Owasp.CsrfGuard.properties文件
将以下依赖项添加到Maven POM(pom.xml
)文件以使用该库:
<dependency>
<groupId>org.owasp</groupId>
<artifactId>csrfguard</artifactId>
<version>3.1.0</version>
</dependency>
- 1
- 2
- 3
- 4
- 5
或者将二进制:从Maven Central下载二进制版本jar文件复制到应用程序的类路径中。
声明CsrfGuard上下文参数以及HttpSessionListener和Filter。
web.xml
:
<!-- 两个参数:
CSRFGuard将按照外观顺序搜索以下位置来搜索指定的属性文件:应用程序的类路径,容器可访问的目录或任意绝对路径。-->
<!-- 两个上下文参数:Owasp.CsrfGuard.Config和Owasp.CsrfGuard.Config.Print。
Owasp.CsrfGuard.Config参数是必需的,它指定CSRFGuard属性文件的位置。默认为:Owasp.CsrfGuard.properties。CSRFGuard将按照外观顺序搜索以下位置来搜索指定的属性文件:应用程序的类路径,容器可访问的目录或任意绝对路径。
Owasp.CsrfGuard.Config.Print参数是可选的,只是指示CSRFGuard将解析的属性显示到应用程序服务器日志文件。-->
<!-- 注:Owasp.CsrfGuard.properties文件可以配置多个文件覆盖。 -->
<listener>
<listener-class>org.owasp.csrfguard.CsrfGuardServletContextListener</listener-class>
</listener>
<!-- 声明并启用CSRFGuard HttpSessionListener:根据session生成token -->
<listener>
<listener-class>org.owasp.csrfguard.CsrfGuardHttpSessionListener</listener-class>
</listener>
<!-- CsrfGuardFilter负责促进JavaEE Web应用程序中CsrfGuard对象和相关令牌验证逻辑的集成。 -->
<filter>
<filter-name>CSRFGuard</filter-name>
<filter-class>org.owasp.csrfguard.CsrfGuardFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>CSRFGuard</filter-name>
<!-- 过滤所有请求,映射到我们想要保护免受攻击的所有资源。 -->
<url-pattern>/*</url-pattern>
</filter-mapping>
<!-- 声明并配置JavaScriptServlet。强烈建议默认使用JavaScript令牌注入策略,Token注入逻辑是自动化的,改动最小。
详见:https://www.owasp.org/index.php/CSRFGuard_3_Token_Injection#JavaScript_DOM_Manipulation -->
<servlet>
<servlet-name>JavaScriptServlet</servlet-name>
<servlet-class>org.owasp.csrfguard.servlet.JavaScriptServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>JavaScriptServlet</servlet-name>
<url-pattern>/JavaScriptServlet</url-pattern>
</servlet-mapping>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
配置
最重要的地方是配置Owasp.CsrfGuard.properties文件。在运行OWASP CSRFGuard实例之前,用户应查看并指定最少数量的配置设置。此类配置包括指定新Token登录页面,为使用XMLHttpRequest的应用程序启用Ajax支持,设置不应受保护的页面,以及配置在识别CSRF攻击时应调用的一个或多个操作。本文的目的是提供关键OWASP CSRFGuard配置设置的概述。
日志记录
org.owasp.csrfguard.Logger = org.owasp.csrfguard.log.ConsoleLogger
- 1
登陆页面Token
org.owasp.csrfguard.NewTokenLandingPage=%servletContext%/index.html
- 1
页面唯一Token
org.owasp.csrfguard.TokenPerPage=true
- 1
Token轮换
org.owasp.csrfguard.Rotate = false
- 1
Ajax和XMLHttpRequest支持
org.owasp.csrfguard.Ajax=true
- 1
不受保护的页面
默认值:CSRFGuard必须验证所请求的资源。
示例1:请求uri和不受保护的页面之间的完全匹配。例如:/Owasp.CsrfGuard.Test/tag.jsp
示例2:最长路径前缀匹配。例如:/test/JavaScriptServlet
示例3:正则扩展匹配。例如:*.html
、/MySite/Public/*
org.owasp.csrfguard.unprotected.Tag=/test/tag.jsp
org.owasp.csrfguard.unprotected.JavaScriptServlet=/test/JavaScriptServlet
org.owasp.csrfguard.unprotected.Html=*.html
org.owasp.csrfguard.unprotected.Public=/MySite/Public/*
- 1
- 2
- 3
- 4
注:该表格只是简单的一个解释。具体详细介绍还看下面的配置文件及官网。
属性 | 值 | 语义 |
---|---|---|
org.owasp.csrfguard.Logger |
JavaLogger /ConsoleLogger |
负责处理CSRFGuard生成的所有日志消息的对象。 |
org.owasp.csrfguard.Enabled |
true |
启用csrfguard过滤器 |
org.owasp.csrfguard.TokenName |
OWASP-CSRFTOKEN |
Token名 |
org.owasp.csrfguard.SessionKey |
OWASP-CSRFTOKEN |
会话密钥名称 |
org.owasp.csrfguard.TokenLength |
32 | Toekn值长度 |
org.owasp.csrfguard.PRNG |
SHA1PRNG |
伪随机数发生器 |
org.owasp.csrfguard.configOverlay.hierarchy |
classpath:Owasp.CsrfGuard.properties, classpath:Owasp.CsrfGuard.overlay.properties |
指定多个配置文件 |
org.owasp.csrfguard.configOverlay.secondsBetweenUpdateChecks |
60 | 检查配置文件是否更新之间的秒数 |
Owasp.CsrfGuard.properties
# The OWASP CSRFGuard Project, BSD License
# Eric Sheridan (eric@infraredsecurity.com), Copyright (c) 2011
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
#
# 1. Redistributions of source code must retain the above copyright notice,
# this list of conditions and the following disclaimer.
# 2. Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
# 3. Neither the name of OWASP nor the names of its contributors may be used
# to endorse or promote products derived from this software without specific
# prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
# ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
# From: https://github.com/esheri3/OWASP-CSRFGuard/blob/master/csrfguard-test/src/main/webapp/WEB-INF/csrfguard.properties
# Common substitutions
# %servletContext% is the servlet context (e.g. the configured app prefix or war file name, or blank.
# e.g. if you deploy a default warfile as someApp.war, then %servletContext% will be /someApp
# if there isnt a context it will be the empty string. So to use this in the configuration, use e.g. %servletContext%/something.html
# which will translate to e.g. /someApp/something.html
# Logger
#
# The logger property (org.owasp.csrfguard.Logger) defines the qualified class name of
# the object responsible for processing all log messages produced by CSRFGuard. The default
# CSRFGuard logger is org.owasp.csrfguard.log.ConsoleLogger. This class logs all messages
# to System.out which JavaEE application servers redirect to a vendor specific log file.
# Developers can customize the logging behavior of CSRFGuard by implementing the
# org.owasp.csrfguard.log.ILogger interface and setting the logger property to the new
# logger's qualified class name. The following configuration snippet instructs OWASP CSRFGuard
# to capture all log messages to the console:
#
# org.owasp.csrfguard.Logger=org.owasp.csrfguard.log.ConsoleLogger
org.owasp.csrfguard.Logger=org.owasp.csrfguard.log.JavaLogger
# Which configuration provider factory you want to use. The default is org.owasp.csrfguard.config.PropertiesConfigurationProviderFactory
# Another configuration provider has more features including config overlays: org.owasp.csrfguard.config.overlay.ConfigurationOverlayProviderFactory
# The default configuration provider is: org.owasp.csrfguard.config.overlay.ConfigurationAutodetectProviderFactory
# which will look for an overlay file, it is there, and the factory inside that file is set it will use it, otherwise will be PropertiesConfigurationProviderFactory
# it needs to implement org.owasp.csrfguard.config.ConfigurationProviderFactory
org.owasp.csrfguard.configuration.provider.factory = org.owasp.csrfguard.config.overlay.ConfigurationAutodetectProviderFactory
# If csrfguard filter is enabled
org.owasp.csrfguard.Enabled = true
# If csrf guard filter should check even if there is no session for the user
# Note: this changed around 2014/04, the default behavior used to be to
# not check if there is no session. If you want the legacy behavior (if your app
# is not susceptible to CSRF if the user has no session), set this to false
org.owasp.csrfguard.ValidateWhenNoSessionExists = true
# New Token Landing Page
#
# The new token landing page property (org.owasp.csrfguard.NewTokenLandingPage) defines where
# to send a user if the token is being generated for the first time, and the use new token landing
# page boolean property (org.owasp.csrfguard.UseNewTokenLandingPage) determines if any redirect happens.
# UseNewTokenLandingPage defaults to false if NewTokenLandingPage is not specified, and to true
# if it is specified.. If UseNewTokenLandingPage is set true then this request is generated
# using auto-posting forms and will only contain the CSRF prevention token parameter, if
# applicable. All query-string or form parameters sent with the original request will be
# discarded. If this property is not defined, CSRFGuard will instead auto-post the user to the
# original context and servlet path. The following configuration snippet instructs OWASP CSRFGuard to
# redirect the user to %servletContext%/index.html when the user visits a protected resource
# without having a corresponding CSRF token present in the HttpSession object:
#
# org.owasp.csrfguard.NewTokenLandingPage=%servletContext%/index.html
# Protected Methods
#
# The protected methods property (org.owasp.csrfguard.ProtectedMethods) defines a comma
# separated list of HTTP request methods that should be protected by CSRFGuard. The default
# list is an empty list which will cause all HTTP methods to be protected, thus preserving
# legacy behavior. This setting allows the user to inform CSRFGuard that only requests of the
# given types should be considered for protection. All HTTP methods not in the list will be
# considered safe (i.e. view only / unable to modify data). This should be used only when the
# user has concrete knowledge that all requests made via methods not in the list
# are safe (i.e. do not apply an action to any data) since it can actually introduce new
# security vulnerabilities. For example: the user thinks that all actionable requests are
# only available by POST requests when in fact some are available via GET requests. If the
# user has excluded GET requests from the list then they have introduced a vulnerability.
# The following configuration snippet instructs OWASP CSRFGuard to protect only the POST,
# PUT, and DELETE HTTP methods.
#
# org.owasp.csrfguard.ProtectedMethods=POST,PUT,DELETE
# or you can configure all to be protected, and specify which is unprotected. This is the preferred approach
# org.owasp.csrfguard.UnprotectedMethods=GET
# Unique Per-Page Tokens
#
# The unique token per-page property (org.owasp.csrfguard.TokenPerPage) is a boolean value that
# determines if CSRFGuard should make use of unique per-page (i.e. URI) prevention tokens as
# opposed to unique per-session prevention tokens. When a user requests a protected resource,
# CSRFGuard will determine if a page specific token has been previously generated. If a page
# specific token has not yet been previously generated, CSRFGuard will verify the request was
# submitted with the per-session token intact. After verifying the presence of the per-session token,
# CSRFGuard will create a page specific token that is required for all subsequent requests to the
# associated resource. The per-session CSRF token can only be used when requesting a resource for
# the first time. All subsequent requests must have the per-page token intact or the request will
# be treated as a CSRF attack. This behavior can be changed with the org.owasp.csrfguard.TokenPerPagePrecreate
# property. Enabling this property will make CSRFGuard calculate the per page token prior to a first
# visit. This option only works with JSTL token injection and is useful for preserving the validity of
# links if the user pushes the back button. There may be a performance impact when enabling this option
# if the .jsp has a large number of proctected links that need tokens to be calculated.
# Use of the unique token per page property is currently experimental
# but provides a significant amount of improved security. Consider the exposure of a CSRF token using
# the legacy unique per-session model. Exposure of this token facilitates the attacker's ability to
# carry out a CSRF attack against the victim's active session for any resource exposed by the web
# application. Now consider the exposure of a CSRF token using the experimental unique token per-page
# model. Exposure of this token would only allow the attacker to carry out a CSRF attack against the
# victim's active session for a small subset of resources exposed by the web application. Use of the
# unique token per-page property is a strong defense in depth strategy significantly reducing the
# impact of exposed CSRF prevention tokens. The following configuration snippet instructs OWASP
# CSRFGuard to utilize the unique token per-page model:
#
# org.owasp.csrfguard.TokenPerPage=true
# org.owasp.csrfguard.TokenPerPagePrecreate=false
org.owasp.csrfguard.TokenPerPage=true
org.owasp.csrfguard.TokenPerPagePrecreate=false
# Token Rotation
#
# The rotate token property (org.owasp.csrfguard.Rotate) is a boolean value that determines if
# CSRFGuard should generate and utilize a new token after verifying the previous token. Rotation
# helps minimize the window of opportunity an attacker has to leverage the victim's stolen token
# in a targeted CSRF attack. However, this functionality generally causes navigation problems in
# most applications. Specifically, the 'Back' button in the browser will often cease to function
# properly. When a user hits the 'Back' button and interacts with the HTML, the browser may submit
# an old token causing CSRFGuard to incorrectly believe this request is a CSRF attack in progress
# (i.e. a 'false positive'). Users can prevent this scenario by preventing the caching of HTML pages
# containing FORM submissions using the cache-control header. However, this may also introduce
# performance problems as the browser will have to request HTML on a more frequent basis. The following
# configuration snippet enables token rotation:
#
# org.owasp.csrfguard.Rotate=true
# Ajax and XMLHttpRequest Support
#
# The Ajax property (org.owasp.csrfguard.Ajax) is a boolean value that indicates whether or not OWASP
# CSRFGuard should support the injection and verification of unique per-session prevention tokens for
# XMLHttpRequests. To leverage Ajax support, the user must not only set this property to true but must
# also reference the JavaScript DOM Manipulation code using a script element. This dynamic script will
# override the send method of the XMLHttpRequest object to ensure the submission of an X-Requested-With
# header name value pair coupled with the submission of a custom header name value pair for each request.
# The name of the custom header is the value of the token name property and the value of the header is
# always the unique per-session token value. This custom header is analogous to the HTTP parameter name
# value pairs submitted via traditional GET and POST requests. If the X-Requested-With header was sent
# in the HTTP request, then CSRFGuard will look for the presence and ensure the validity of the unique
# per-session token in the custom header name value pair. Note that verification of these headers takes
# precedence over verification of the CSRF token supplied as an HTTP parameter. More specifically,
# CSRFGuard does not verify the presence of the CSRF token if the Ajax support property is enabled and
# the corresponding X-Requested-With and custom headers are embedded within the request. The following
# configuration snippet instructs OWASP CSRFGuard to support Ajax requests by verifying the presence and
# correctness of the X-Requested-With and custom headers:
#
# org.owasp.csrfguard.Ajax=true
org.owasp.csrfguard.Ajax=true
# The default behavior of CSRFGuard is to protect all pages. Pages marked as unprotected will not be protected.
# If the Protect property is enabled, this behavior is reversed. Pages must be marked as protected to be protected.
# All other pages will not be protected. This is useful when the CsrfGuardFilter is aggressively mapped (ex: /*),
# but you only want to protect a few pages.
#
# org.owasp.csrfguard.Protect=true
# Unprotected Pages:
#
# The unprotected pages property (org.owasp.csrfguard.unprotected.*) defines a series of pages that
# should not be protected by CSRFGuard. Such configurations are useful when the CsrfGuardFilter is
# aggressively mapped (ex: /*). The syntax of the property name is org.owasp.csrfguard.unprotected.[PageName],
# where PageName is some arbitrary identifier that can be used to reference a resource. The syntax of
# defining the uri of unprotected pages is the same as the syntax used by the JavaEE container for uri mapping.
# Specifically, CSRFGuard will identify the first match (if any) between the requested uri and an unprotected
# page in order of declaration. Match criteria is as follows:
#
# Case 1: exact match between request uri and unprotected page
# Case 2: longest path prefix match, beginning / and ending /*
# Case 3: extension match, beginning *.
# Case 4: if the value starts with ^ and ends with $, it will be evaulated as a regex. Note that before the
# regex is compiled, any common variables will be substituted (e.g. %servletContext%)
# Default: requested resource must be validated by CSRFGuard
#
# The following code snippet illustrates the four use cases over four examples. The first two examples
# (Tag and JavaScriptServlet) look for direct URI matches. The third example (Html) looks for all resources
# ending in a .html extension. The next example (Public) looks for all resources prefixed with the URI path /MySite/Public/*.
# The last example looks for resources that end in Public.do
#
# org.owasp.csrfguard.unprotected.Tag=%servletContext%/tag.jsp
# org.owasp.csrfguard.unprotected.JavaScriptServlet=%servletContext%/JavaScriptServlet
# org.owasp.csrfguard.unprotected.Html=*.html
# org.owasp.csrfguard.unprotected.Public=%servletContext%/Public/*
# regex example starts with ^ and ends with $, and the %servletContext% is evaluated before the regex
# org.owasp.csrfguard.unprotected.PublicServlet=^%servletContext%/.*Public\.do$
#org.owasp.csrfguard.unprotected.Default=%servletContext%/
#org.owasp.csrfguard.unprotected.Upload=%servletContext%/upload.html
#org.owasp.csrfguard.unprotected.JavaScriptServlet=%servletContext%/JavaScriptServlet
#org.owasp.csrfguard.unprotected.Ajax=%servletContext%/ajax.html
#org.owasp.csrfguard.unprotected.Error=%servletContext%/error.html
#org.owasp.csrfguard.unprotected.Index=%servletContext%/index.html
#org.owasp.csrfguard.unprotected.JavaScript=%servletContext%/javascript.html
#org.owasp.csrfguard.unprotected.Tag=%servletContext%/tag.jsp
#org.owasp.csrfguard.unprotected.Redirect=%servletContext%/redirect.jsp
#org.owasp.csrfguard.unprotected.Forward=%servletContext%/forward.jsp
#org.owasp.csrfguard.unprotected.Session=%servletContext%/session.jsp
# Actions: Responding to Attacks
#
# The actions directive (org.owasp.csrfguard.action.*) gives the user the ability to specify one or more
# actions that should be invoked when a CSRF attack is detected. Every action must implement the
# org.owasp.csrfguard.action.IAction interface either directly or indirectly through the
# org.owasp.csrfguard.action.AbstractAction helper class. Many actions accept parameters that can be specified
# along with the action class declaration. These parameters are consumed at runtime and impact the behavior of
# the associated action.
#
# The syntax for defining and configuring CSRFGuard actions is relatively straight forward. Let us assume we wish
# to redirect the user to a default page when a CSRF attack is detected. A redirect action already exists within
# the CSRFGuard bundle and is available via the class name org.owasp.csrfguard.actions.Redirect. In order to enable
# this action, we capture the following declaration in the Owasp.CsrfGuard.properties file:
#
# syntax: org.owasp.csrfguard.action.[actionName]=[className]
# example: org.owasp.csrfguard.action.class.Redirect=org.owasp.csrfguard.actions.Redirect
#
# The aforementioned directive declares an action called "Redirect" (i.e. [actionName]) referencing the Java class
# "org.owasp.csrfguard.actions.Redirect" (i.e. [className]). Anytime a CSRF attack is detected, the Redirect action
# will be executed. You may be asking yourself, "but how do I specify where the user is redirected?"; this is where
# action parameters come into play. In order to specify the redirect location, we capture the following declaration
# in the Owasp.CsrfGuard.properties file:
#
# syntax: org.owasp.csrfguard.action.[actionName].[parameterName]=[parameterValue]
# example: org.owasp.csrfguard.action.Redirect.ErrorPage=%servletContext%/error.html
#
# The aforementioned directive declares an action parameter called "ErrorPage" (i.e. [parameterName]) with the value
# of "%servletContext%/error.html" (i.e. [parameterValue]) for the action "Redirect" (i.e. [actionName]). The
# Redirect action expects the "ErrorPage" parameter to be defined and will redirect the user to this location when
# an attack is detected.
#
#org.owasp.csrfguard.action.Empty=org.owasp.csrfguard.action.Empty
org.owasp.csrfguard.action.Log=org.owasp.csrfguard.action.Log
org.owasp.csrfguard.action.Log.Message=potential cross-site request forgery (CSRF) attack thwarted (user:%user%, ip:%remote_ip%, method:%request_method%, uri:%request_uri%, error:%exception_message%)
#org.owasp.csrfguard.action.Invalidate=org.owasp.csrfguard.action.Invalidate
org.owasp.csrfguard.action.Redirect=org.owasp.csrfguard.action.Redirect
org.owasp.csrfguard.action.Redirect.Page=%servletContext%/error.html
#org.owasp.csrfguard.action.RequestAttribute=org.owasp.csrfguard.action.RequestAttribute
#org.owasp.csrfguard.action.RequestAttribute.AttributeName=Owasp_CsrfGuard_Exception_Key
org.owasp.csrfguard.action.Rotate=org.owasp.csrfguard.action.Rotate
#org.owasp.csrfguard.action.SessionAttribute=org.owasp.csrfguard.action.SessionAttribute
#org.owasp.csrfguard.action.SessionAttribute.AttributeName=Owasp_CsrfGuard_Exception_Key
#org.owasp.csrfguard.action.Error=org.owasp.csrfguard.action.Error
#org.owasp.csrfguard.action.Error.Code=403
#org.owasp.csrfguard.action.Error.Message=Security violation.
# Token Name
#
# The token name property (org.owasp.csrfguard.TokenName) defines the name of the HTTP parameter
# to contain the value of the OWASP CSRFGuard token for each request. The following configuration
# snippet sets the CSRFGuard token parameter name to the value OWASP-CSRFTOKEN:
#
# org.owasp.csrfguard.TokenName=OWASP-CSRFTOKEN
org.owasp.csrfguard.TokenName=OWASP-CSRFTOKEN
# Session Key
#
# The session key property (org.owasp.csrfguard.SessionKey) defines the string literal used to save
# and lookup the CSRFGuard token from the session. This value is used by the filter and the tag
# libraries to retrieve and set the token value in the session. Developers can use this key to
# programmatically lookup the token within their own code. The following configuration snippet sets
# the session key to the value OWASP_CSRFTOKEN:
#
# org.owasp.csrfguard.SessionKey=OWASP_CSRFTOKEN
org.owasp.csrfguard.SessionKey=OWASP_CSRFTOKEN
# Token Length
#
# The token length property (org.owasp.csrfguard.TokenLength) defines the number of characters that
# should be found within the CSRFGuard token. Note that characters are delimited by dashes (-) in groups
# of four. For cosmetic reasons, users are encourage to ensure the token length is divisible by four.
# The following configuration snippet sets the token length property to 32 characters:
#
# org.owasp.csrfguard.TokenLength=32
org.owasp.csrfguard.TokenLength=32
# Pseudo-random Number Generator
#
# The pseudo-random number generator property (org.owasp.csrfguard.PRNG) defines what PRNG should be used
# to generate the OWASP CSRFGuard token. Always ensure this value references a cryptographically strong
# pseudo-random number generator algorithm. The following configuration snippet sets the pseudo-random number
# generator to SHA1PRNG:
#
# org.owasp.csrfguard.PRNG=SHA1PRNG
org.owasp.csrfguard.PRNG=SHA1PRNG
# Pseudo-random Number Generator Provider
# The pseudo-random number generator provider property (org.owasp.csrfguard.PRNG.Provider) defines which
# provider's implementation of org.owasp.csrfguard.PRNG we should utilize. The following configuration
# snippet instructs the JVM to leverage SUN's implementation of the algorithm denoted by the
# org.owasp.csrfguard.PRNG property:
# org.owasp.csrfguard.PRNG.Provider=SUN
org.owasp.csrfguard.PRNG.Provider=SUN
# If not specifying the print config option in the web.xml, you can specify it here, to print the config
# on startup
org.owasp.csrfguard.Config.Print = true
###########################
## Javascript servlet settings if not set in web.xml
## https://www.owasp.org/index.php/CSRFGuard_3_Token_Injection
###########################
# leave this blank and blank in web.xml and it will read from META-INF/csrfguard.js from the jarfile
# 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.
org.owasp.csrfguard.JavascriptServlet.sourceFile = /script/csrfguard.js
# 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.
org.owasp.csrfguard.JavascriptServlet.domainStrict = true
# 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.
org.owasp.csrfguard.JavascriptServlet.cacheControl = private, maxage=28800
# 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.
org.owasp.csrfguard.JavascriptServlet.refererPattern = .*
# Similar to javascript servlet referer pattern, but this will make sure the referer of the
# javascript servlet matches the domain of the request. If there is no referer (proxy strips it?)
# then it will not fail. Generally this is a good idea to be true.
org.owasp.csrfguard.JavascriptServlet.refererMatchDomain = true
# 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.
org.owasp.csrfguard.JavascriptServlet.injectIntoForms = true
# if the token should be injected in GET forms (which will be on the URL)
# if the HTTP method GET is unprotected, then this should likely be false
org.owasp.csrfguard.JavascriptServlet.injectGetForms = true
# if the token should be injected in the action in forms
# note, if injectIntoForms is true, then this might not need to be true
org.owasp.csrfguard.JavascriptServlet.injectFormAttributes = true
# 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.
org.owasp.csrfguard.JavascriptServlet.injectIntoAttributes = true
org.owasp.csrfguard.JavascriptServlet.xRequestedWith = OWASP CSRFGuard Project
###########################
## Config overlay settings if you have the provider above set to ConfigurationOverlayProvider
## This CSRF config provider uses Internet2 Configuration Overlays (documented on Internet2 wiki)
## By default the configuration is read from the Owasp.CsrfGuard.properties
## (which should not be edited), and the Owasp.CsrfGuard.overlay.properties overlays
## the base settings. See the Owasp.CsrfGuard.properties for the possible
## settings that can be applied to the Owasp.CsrfGuard.overlay.properties
###########################
# comma separated config files that override each other (files on the right override the left)
# each should start with file: or classpath:
# e.g. classpath:Owasp.CsrfGuard.properties, file:c:/temp/myFile.properties
org.owasp.csrfguard.configOverlay.hierarchy = classpath:Owasp.CsrfGuard.properties, classpath:Owasp.CsrfGuard.overlay.properties
# seconds between checking to see if the config files are updated
org.owasp.csrfguard.configOverlay.secondsBetweenUpdateChecks = 60
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
- 80
- 81
- 82
- 83
- 84
- 85
- 86
- 87
- 88
- 89
- 90
- 91
- 92
- 93
- 94
- 95
- 96
- 97
- 98
- 99
- 100
- 101
- 102
- 103
- 104
- 105
- 106
- 107
- 108
- 109
- 110
- 111
- 112
- 113
- 114
- 115
- 116
- 117
- 118
- 119
- 120
- 121
- 122
- 123
- 124
- 125
- 126
- 127
- 128
- 129
- 130
- 131
- 132
- 133
- 134
- 135
- 136
- 137
- 138
- 139
- 140
- 141
- 142
- 143
- 144
- 145
- 146
- 147
- 148
- 149
- 150
- 151
- 152
- 153
- 154
- 155
- 156
- 157
- 158
- 159
- 160
- 161
- 162
- 163
- 164
- 165
- 166
- 167
- 168
- 169
- 170
- 171
- 172
- 173
- 174
- 175
- 176
- 177
- 178
- 179
- 180
- 181
- 182
- 183
- 184
- 185
- 186
- 187
- 188
- 189
- 190
- 191
- 192
- 193
- 194
- 195
- 196
- 197
- 198
- 199
- 200
- 201
- 202
- 203
- 204
- 205
- 206
- 207
- 208
- 209
- 210
- 211
- 212
- 213
- 214
- 215
- 216
- 217
- 218
- 219
- 220
- 221
- 222
- 223
- 224
- 225
- 226
- 227
- 228
- 229
- 230
- 231
- 232
- 233
- 234
- 235
- 236
- 237
- 238
- 239
- 240
- 241
- 242
- 243
- 244
- 245
- 246
- 247
- 248
- 249
- 250
- 251
- 252
- 253
- 254
- 255
- 256
- 257
- 258
- 259
- 260
- 261
- 262
- 263
- 264
- 265
- 266
- 267
- 268
- 269
- 270
- 271
- 272
- 273
- 274
- 275
- 276
- 277
- 278
- 279
- 280
- 281
- 282
- 283
- 284
- 285
- 286
- 287
- 288
- 289
- 290
- 291
- 292
- 293
- 294
- 295
- 296
- 297
- 298
- 299
- 300
- 301
- 302
- 303
- 304
- 305
- 306
- 307
- 308
- 309
- 310
- 311
- 312
- 313
- 314
- 315
- 316
- 317
- 318
- 319
- 320
- 321
- 322
- 323
- 324
- 325
- 326
- 327
- 328
- 329
- 330
- 331
- 332
- 333
- 334
- 335
- 336
- 337
- 338
- 339
- 340
- 341
- 342
- 343
- 344
- 345
- 346
- 347
- 348
- 349
- 350
- 351
- 352
- 353
- 354
- 355
- 356
- 357
- 358
- 359
- 360
- 361
- 362
- 363
- 364
- 365
- 366
- 367
- 368
- 369
- 370
- 371
- 372
- 373
- 374
- 375
- 376
- 377
- 378
- 379
- 380
- 381
- 382
- 383
- 384
- 385
- 386
- 387
- 388
- 389
- 390
- 391
- 392
- 393
- 394
- 395
- 396
- 397
- 398
- 399
- 400
- 401
- 402
- 403
- 404
- 405
- 406
- 407
- 408
- 409
自定义覆盖配置:Owasp.CsrfGuard.overlay.properties
上面文件可采用官网默认,此文件可以进行自定义修改。
org.owasp.csrfguard.configuration.provider.factory=org.owasp.csrfguard.config.overlay.ConfigurationOverlayProviderFactory
org.owasp.csrfguard.JavascriptServlet.refererPattern = http://localhost:80.*
org.owasp.csrfguard.unprotected.Default=%servletContext%/
org.owasp.csrfguard.unprotected.Upload=%servletContext%/upload.html
org.owasp.csrfguard.unprotected.JavaScriptServlet=%servletContext%/JavaScriptServlet
org.owasp.csrfguard.unprotected.Ajax=%servletContext%/ajax.html
org.owasp.csrfguard.unprotected.Error=%servletContext%/error.html
org.owasp.csrfguard.unprotected.Index=%servletContext%/index.html
org.owasp.csrfguard.unprotected.JavaScript=%servletContext%/javascript.html
org.owasp.csrfguard.unprotected.Tag=%servletContext%/tag.jsp
org.owasp.csrfguard.unprotected.Redirect=%servletContext%/redirect.jsp
org.owasp.csrfguard.unprotected.Forward=%servletContext%/forward.jsp
org.owasp.csrfguard.unprotected.Session=%servletContext%/session.jsp
org.owasp.csrfguard.unprotected.Favicon=%servletContext%/favicon.ico
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
Token注入
OWASP CSRFGuard的用户可以使用两种策略将预防令牌注入HTML:
- JavaScript DOM操作 - 主要是自动化过程,只需要很少的工作量,是大多数Web应用程序的理想选择
- JSP标记库 - 提供细粒度策略,适用于自动DOM操作不足的情况。
JavaScript DOM操作
web.xml
声明并配置JavaScriptServlet:
<!-- 声明并配置JavaScriptServlet。强烈建议默认使用JavaScript令牌注入策略,Token注入逻辑是自动化的,改动最小。
详见:https://www.owasp.org/index.php/CSRFGuard_3_Token_Injection#JavaScript_DOM_Manipulation -->
<servlet>
<servlet-name>JavaScriptServlet</servlet-name>
<servlet-class>org.owasp.csrfguard.servlet.JavaScriptServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>JavaScriptServlet</servlet-name>
<url-pattern>/JavaScriptServlet</url-pattern>
</servlet-mapping>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
还需配置参数:sourceFile
org.owasp.csrfguard.JavascriptServlet.sourceFile = /script/csrfguard.js
- 1
注入动态JavaScript:在公共jsp里面或者需要注入的页面中加入即可。
<script src="/JavaScriptServlet"></script>
- 1
JSP标记库
页面中:
<%@ taglib uri="http://www.owasp.org/index.php/Category:OWASP_CSRFGuard_Project/Owasp.CsrfGuard.tld" prefix="csrf" %>
- 1
注意:csrf:tokenvalue
的属性uri
必填。由于公司项目中url提交格式是/xxxx?save
。实际uri为/xxxx
。
显示Token名称
<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:tokenname/>" value="<csrf:tokenvalue uri="protect.html"/>"/>
</form>
- 1
- 2
- 3
- 4
- 5
显示Token值
<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:tokenname/>" value="<csrf:tokenvalue/>"/>
</form>
- 1
- 2
- 3
- 4
- 5
使用预防令牌生成链接
<a href="protect.html?<csrf:token/>">protect.html</a>
<a href="protect.html?<csrf:token uri="protect.html"/>">protect.html</a>
<csrf:a href="protect.html">protect.html</csrf:a>
- 1
- 2
- 3
- 4
使用预防令牌生成表单
<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>
- 1
- 2
- 3
- 4
转-OWASP CSRFGuard使用细节的更多相关文章
- 转-CSRF&OWASP CSRFGuard
一. 什么是CSRF?CSRF(Cross-Site Request Forgery)直译的话就是跨站点请求伪造也就是说在用户会话下对某个需要验证的网络应用发送GET/POST请求——而这些请求是未经 ...
- CSRFGuard工具介绍
理解CSRFGuard的基础:http://www.runoob.com/jsp/jsp-tutorial.html 1:您需要做的第一件事是将OWASP.CSRFARGAD.JAR库复制到类路径中. ...
- CSRF 攻击原理和防御方法
1. CSRF攻击原理 CSRF(Cross site request forgery),即跨站请求伪造.我们知道XSS是跨站脚本攻击,就是在用户的浏览器中执行攻击者的脚本,来获得其cookie等信息 ...
- XSS 自动化检测 Fiddler Watcher & x5s & ccXSScan 初识
一.标题:XSS 自动化检测 Fiddler Watcher & x5s & ccXSScan 初识 automated XSS testing assistant 二.引言 ...
- XSS自动化检测 Fiddler Watcher & x5s & ccXSScan 初识
一.标题:XSS 自动化检测 Fiddler Watcher & x5s & ccXSScan 初识 automated XSS testing assistant 二.引言 ...
- Appscan漏洞之跨站点请求伪造(CSRF)
公司前段时间使用了Fortify扫描项目代码,在修复完这些Fortify漏洞后,最近又启用了Appscan对项目代码进行漏洞扫描,同样也是安排了本人对这些漏洞进行修复.现在,针对修复过的Appscan ...
- ASP.NET Core中的OWASP Top 10 十大风险-SQL注入
不定时更新翻译系列,此系列更新毫无时间规律,文笔菜翻译菜求各位看官老爷们轻喷,如觉得我翻译有问题请挪步原博客地址 本博文翻译自: https://dotnetcoretutorials.com/201 ...
- OWASP SSL 高级审查工具
http://www.linuxidc.com/Linux/2016-03/129164.htm InfoWorld 在部署.运营和保障网络安全领域精选出了年度开源工具获奖者. 最佳开源网络和安全软件 ...
- OWASP 关于会话管理 - 译文 [原创]
英文原文:https://github.com/OWASP/CheatSheetSeries/blob/master/cheatsheets/Session_Management_Cheat_Shee ...
随机推荐
- ruby数据库表添加字段、修改字段类型、修改字段名称
Rails 手册 3.8 使用 change 方法 1.为表添加字段 rails g migration add_column_to_d_groups_equip_num class AddColum ...
- JQuery和ASP.NET分别实现级联下拉框效果
在学习JQuery之前知道下拉框的级联效果可以通过asp.net控件实现,现在学习了JQuery,知道了JQuery和select也能实现.我分别举两个小例子说明这两种方法如何实现. 1.用JQuer ...
- java 写一个 map reduce 矩阵相乘的案例
1.写一个工具类用来生成 map reduce 实验 所需 input 文件 下面两个是原始文件 matrix1.txt 1 2 -2 0 3 3 4 -3 -2 0 2 3 5 3 -1 2 -4 ...
- 关于selenium的那些坑
selenium 辅助工具 splinter 总有人看不明白,以防万一,先在开头大写加粗说明一下: frameset不用切,frame需层层切! 很多人在用selenium定位页面元素的时候会遇到定位 ...
- 054、准备 macvlan环境(2019-03-21 周四)
参考https://www.cnblogs.com/CloudMan6/p/7352620.html 除了overlay,docker还开发了另一个支持跨主机容器网络的 driver :macvl ...
- python保存文件到数据库
效果 model class WEIGUI_IMG(Base): __tablename__ = 'DW_ZHS_D_WEIGUI_IMG' # 表名 id = Column(), primary_k ...
- 路由器数据统计SQL脚本
一.路由器部分 //[饼图]统计路由器在线.离线数量 SELECT COUNT(*) AS total, MINUTE)) ELSE NULL END) AS livecount, MINUTE)) ...
- GCC编译器原理(一)05------GCC 工具:readelf、size、strings、strip和 windres
1.3.18 readelf:elf 文件格式分析工具 这个工具和 objdump 命令提供的功能类似,但是它显示的信息更为具体,并且它不依赖 BFD 库( BFD 库是一个 GNU 项目,它的目标就 ...
- 【D3D】Directx12运行报错&win10无法添加【图形工具】
“我欢欣雀跃地打开<3D programming with Directx12>,准备接受D3D的洗礼,然后就卡在了 chapter 0 .”——Liez 100%纯小白的chapter ...
- postfix 指定用户限制指定域名收发
main.cf 配置示例: smtpd_restriction_classes = local_in_only, local_out_only local_in_only = check_recipi ...