Java Spring MVC 中的 CSRF(跨站请求伪造)保护
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/22555110/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
CSRF (Cross-site request forgery) protection in spring MVC
提问by Ravindu
I'm little confuse in this CSRF (Cross-site request forgery) protection in spring. No I have my jsp and my controller and a web service. What I want to do is validate the token at the web service level and if token is a match, run the web service (In my case do a db insert)
我对 Spring 的 CSRF(跨站点请求伪造)保护有点困惑。不,我有我的 jsp、我的控制器和一个 Web 服务。我想要做的是在 Web 服务级别验证令牌,如果令牌匹配,则运行 Web 服务(在我的情况下执行 db insert)
JSP file
JSP文件
<form:input type="text" class="form-control" path="mName" />
<input type="hidden" name="${_csrf.parameterName}"
value="${_csrf.token}" />
<div class="form-action">
<input type="submit" value="Save" class="btn btn-primary" />
</div>
</form:form>
I've inserted the hidden tag also. Now what should I do to validate this token. I'm little lost there.
我也插入了隐藏标签。现在我应该怎么做来验证这个令牌。我有点迷失在那里。
At the controller class I get the values from the form to an object and call the web ervise to save data
在控制器类中,我从表单中获取值到一个对象并调用 web ervise 来保存数据
@RequestMapping(method = RequestMethod.POST)
public String processForm(@ModelAttribute(value = "userForm") @Valid UserForm userForm, BindingResult result, ModelMap model) {
//call the web service
}
采纳答案by Ravindu
Apparently I was using spring security 3.1.4.RELEASE. here you have do this manually. Then I changed it to 3.2.2.RELEASEand then I just had to use
显然我正在使用 spring security 3.1.4.RELEASE。在这里,您可以手动执行此操作。然后我将其更改为3.2.2.RELEASE然后我只需要使用
<input type="hidden" name="${_csrf.parameterName}" value="${_csrf.token}" />
Refer this link to see whats new in spring security 3.2
请参阅此链接以查看 Spring Security 3.2 的新功能
http://docs.spring.io/spring-security/site/docs/3.2.0.RELEASE/reference/htmlsingle/#new
http://docs.spring.io/spring-security/site/docs/3.2.0.RELEASE/reference/htmlsingle/#new
Be careful, when you change from 3.1.4.RELEASE to 3.2.2.RELEASE, there are lot of confusing re factorings to do. Specially in web.xmland spring-security.xmlfiles
请注意,当您从 3.1.4.RELEASE 更改为 3.2.2.RELEASE 时,需要进行很多令人困惑的重构。特别是在web.xml和spring-security.xml文件中
回答by Shishir Kumar
OWASP Enterprise Security APIhas a very good option offering solid protection against CSRF. CSRF is actually pretty easy to solve. OWASP ESAPI provides the specifications to implement CSRF protection as below.
OWASP Enterprise Security API有一个很好的选择,可以提供针对 CSRF 的可靠保护。CSRF实际上很容易解决。OWASP ESAPI 提供了实现 CSRF 保护的规范如下。
1. Generate new CSRF token and add it to user once on login and store user in http session.
1. 生成新的 CSRF 令牌并在登录时将其添加到用户并将用户存储在 http 会话中。
This is done in the default ESAPI implementation, and it is stored as a member variable of the User
object that gets stored in the session
.
这是在默认的 ESAPI 实现中完成的,它作为User
对象的成员变量存储在session
.
/this code is in the DefaultUser implementation of ESAPI
/** This user's CSRF token. */
private String csrfToken = resetCSRFToken();
...
public String resetCSRFToken() {
csrfToken = ESAPI.randomizer().getRandomString(8, DefaultEncoder.CHAR_ALPHANUMERICS);
return csrfToken;
}
2. On any forms or urls that should be protected, add the token as a parameter / hidden field.
2. 在任何应该保护的表单或 url 上,添加令牌作为参数/隐藏字段。
The addCSRFToken
method below should be called for any url that is going to be rendered that needs CSRF protection. Alternatively if you are creating a form, or have another technique of rendering URLs (like c:url
), then be sure to add a parameter or hidden field with the name "ctoken
" and the value of DefaultHTTPUtilities.getCSRFToken()
.
在addCSRFToken
下面的方法应该被称为为将要呈现的是需要CSRF保护的任何URL。或者,如果您正在创建表单,或使用其他呈现 URL 的技术(如c:url
),请确保添加名称为“ ctoken
”且值为 的参数或隐藏字段DefaultHTTPUtilities.getCSRFToken()
。
//from HTTPUtilitiles interface
final static String CSRF_TOKEN_NAME = "ctoken";
//this code is from the DefaultHTTPUtilities implementation in ESAPI
public String addCSRFToken(String href) {
User user = ESAPI.authenticator().getCurrentUser();
if (user.isAnonymous()) {
return href;
}
// if there are already parameters append with &, otherwise append with ?
String token = CSRF_TOKEN_NAME + "=" + user.getCSRFToken();
return href.indexOf( '?') != -1 ? href + "&" + token : href + "?" + token;
}
...
public String getCSRFToken() {
User user = ESAPI.authenticator().getCurrentUser();
if (user == null) return null;
return user.getCSRFToken();
}
3. On the server side for those protected actions, check that the submitted token matches the token from the user object in the session.
3. 在这些受保护操作的服务器端,检查提交的令牌是否与会话中用户对象的令牌匹配。
Ensure that you call this method from your servlet
or spring
action or jsf
controller, or whatever server side mechanism you're using to handle requests. This should be called on any request that you need to validate for CSRF protection. Notice that when the tokens do not match, it's considered a possible forged request.
确保您从您的servlet
或spring
操作或jsf
控制器或您用于处理请求的任何服务器端机制调用此方法。这应该在您需要验证 CSRF 保护的任何请求上调用。请注意,当令牌不匹配时,它被视为可能的伪造请求。
//this code is from the DefaultHTTPUtilities implementation in ESAPI
public void verifyCSRFToken(HttpServletRequest request) throws IntrusionException {
User user = ESAPI.authenticator().getCurrentUser();
// check if user authenticated with this request - no CSRF protection required
if( request.getAttribute(user.getCSRFToken()) != null ) {
return;
}
String token = request.getParameter(CSRF_TOKEN_NAME);
if ( !user.getCSRFToken().equals( token ) ) {
throw new IntrusionException("Authentication failed", "Possibly forged HTTP request without proper CSRF token detected");
}
}
4. On logout and session timeout, the user object is removed from the session and the session destroyed.
4. 在注销和会话超时时,从会话中删除用户对象并销毁会话。
In this step, logout is called. When that happens, note that the session is invalidated and the current user object is reset to be an anonymous user, thereby removing the reference to the current user and accordingly the csrf token.
在这一步中,logout 被调用。发生这种情况时,请注意会话无效并且当前用户对象被重置为匿名用户,从而删除对当前用户的引用以及相应的 csrf 令牌。
//this code is in the DefaultUser implementation of ESAPI
public void logout() {
ESAPI.httpUtilities().killCookie( ESAPI.currentRequest(), ESAPI.currentResponse(), HTTPUtilities.REMEMBER_TOKEN_COOKIE_NAME );
HttpSession session = ESAPI.currentRequest().getSession(false);
if (session != null) {
removeSession(session);
session.invalidate();
}
ESAPI.httpUtilities().killCookie(ESAPI.currentRequest(), ESAPI.currentResponse(), "JSESSIONID");
loggedIn = false;
logger.info(Logger.SECURITY_SUCCESS, "Logout successful" );
ESAPI.authenticator().setCurrentUser(User.ANONYMOUS);
}
资料来源:http: //www.jtmelton.com/2010/05/16/the-owasp-top-ten-and-esapi-part-6-cross-site-request-forgery-csrf/
Hope this helps you out.
希望这可以帮助你。
Shishir
石狮