mirror of
https://github.com/yangzongzhuan/RuoYi.git
synced 2025-10-15 10:08:26 +00:00
新增CSRF防护功能
This commit is contained in:
@@ -33,6 +33,7 @@ import com.ruoyi.framework.shiro.session.OnlineSessionFactory;
|
||||
import com.ruoyi.framework.shiro.web.CustomShiroFilterFactoryBean;
|
||||
import com.ruoyi.framework.shiro.web.filter.LogoutFilter;
|
||||
import com.ruoyi.framework.shiro.web.filter.captcha.CaptchaValidateFilter;
|
||||
import com.ruoyi.framework.shiro.web.filter.csrf.CsrfValidateFilter;
|
||||
import com.ruoyi.framework.shiro.web.filter.kickout.KickoutSessionFilter;
|
||||
import com.ruoyi.framework.shiro.web.filter.online.OnlineSessionFilter;
|
||||
import com.ruoyi.framework.shiro.web.filter.sync.SyncOnlineSessionFilter;
|
||||
@@ -132,6 +133,18 @@ public class ShiroConfig
|
||||
@Value("${shiro.rememberMe.enabled: false}")
|
||||
private boolean rememberMe;
|
||||
|
||||
/**
|
||||
* 是否开启csrf
|
||||
*/
|
||||
@Value("${csrf.enabled: false}")
|
||||
private boolean csrfEnabled;
|
||||
|
||||
/**
|
||||
* csrf白名单链接
|
||||
*/
|
||||
@Value("${csrf.whites: ''}")
|
||||
private String csrfWhites;
|
||||
|
||||
/**
|
||||
* 缓存管理器 使用Ehcache实现
|
||||
*/
|
||||
@@ -263,6 +276,17 @@ public class ShiroConfig
|
||||
return logoutFilter;
|
||||
}
|
||||
|
||||
/**
|
||||
* csrf过滤器
|
||||
*/
|
||||
public CsrfValidateFilter csrfValidateFilter()
|
||||
{
|
||||
CsrfValidateFilter csrfValidateFilter = new CsrfValidateFilter();
|
||||
csrfValidateFilter.setEnabled(csrfEnabled);
|
||||
csrfValidateFilter.setCsrfWhites(StringUtils.str2List(csrfWhites, ","));
|
||||
return csrfValidateFilter;
|
||||
}
|
||||
|
||||
/**
|
||||
* Shiro过滤器配置
|
||||
*/
|
||||
@@ -309,13 +333,14 @@ public class ShiroConfig
|
||||
filters.put("onlineSession", onlineSessionFilter());
|
||||
filters.put("syncOnlineSession", syncOnlineSessionFilter());
|
||||
filters.put("captchaValidate", captchaValidateFilter());
|
||||
filters.put("csrfValidateFilter", csrfValidateFilter());
|
||||
filters.put("kickout", kickoutSessionFilter());
|
||||
// 注销成功,则跳转到指定页面
|
||||
filters.put("logout", logoutFilter());
|
||||
shiroFilterFactoryBean.setFilters(filters);
|
||||
|
||||
// 所有请求需要认证
|
||||
filterChainDefinitionMap.put("/**", "user,kickout,onlineSession,syncOnlineSession");
|
||||
filterChainDefinitionMap.put("/**", "user,kickout,onlineSession,syncOnlineSession,csrfValidateFilter");
|
||||
shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);
|
||||
|
||||
return shiroFilterFactoryBean;
|
||||
|
@@ -0,0 +1,76 @@
|
||||
package com.ruoyi.framework.shiro.web.filter.csrf;
|
||||
|
||||
import java.util.List;
|
||||
import javax.servlet.ServletRequest;
|
||||
import javax.servlet.ServletResponse;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import org.apache.shiro.web.filter.AccessControlFilter;
|
||||
import com.ruoyi.common.constant.ShiroConstants;
|
||||
import com.ruoyi.common.core.text.Convert;
|
||||
import com.ruoyi.common.utils.ServletUtils;
|
||||
import com.ruoyi.common.utils.ShiroUtils;
|
||||
import com.ruoyi.common.utils.StringUtils;
|
||||
|
||||
/**
|
||||
* csrf过滤器
|
||||
*
|
||||
* @author ruoyi
|
||||
*/
|
||||
public class CsrfValidateFilter extends AccessControlFilter
|
||||
{
|
||||
/**
|
||||
* 白名单链接
|
||||
*/
|
||||
private List<String> csrfWhites;
|
||||
|
||||
@Override
|
||||
protected boolean isAccessAllowed(ServletRequest request, ServletResponse response, Object mappedValue)
|
||||
throws Exception
|
||||
{
|
||||
HttpServletRequest httpServletRequest = (HttpServletRequest) request;
|
||||
if (!isAllowMethod(httpServletRequest))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
if (StringUtils.matches(httpServletRequest.getServletPath(), csrfWhites))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
return validateResponse(httpServletRequest, httpServletRequest.getHeader(ShiroConstants.CSRF_TOKEN));
|
||||
}
|
||||
|
||||
public boolean validateResponse(HttpServletRequest request, String requestToken)
|
||||
{
|
||||
Object obj = ShiroUtils.getSession().getAttribute(ShiroConstants.CSRF_TOKEN);
|
||||
String sessionToken = Convert.toStr(obj, "");
|
||||
if (StringUtils.isEmpty(requestToken) || !requestToken.equalsIgnoreCase(sessionToken))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean onAccessDenied(ServletRequest request, ServletResponse response) throws Exception
|
||||
{
|
||||
ServletUtils.renderString((HttpServletResponse) response, "{\"code\":\"1\",\"msg\":\"当前请求的安全验证未通过,请刷新页面后重试。\"}");
|
||||
return false;
|
||||
}
|
||||
|
||||
private boolean isAllowMethod(HttpServletRequest request)
|
||||
{
|
||||
String method = request.getMethod();
|
||||
return "POST".equalsIgnoreCase(method);
|
||||
}
|
||||
|
||||
public List<String> getCsrfWhites()
|
||||
{
|
||||
return csrfWhites;
|
||||
}
|
||||
|
||||
public void setCsrfWhites(List<String> csrfWhites)
|
||||
{
|
||||
this.csrfWhites = csrfWhites;
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user