文章目录
- 二、解决方案
- 2.1. 创建CSRF防御统一管理
- 2.2. 创建csrfToken校验
- 2.3. 加密工具类
- 2.4. 查询实战
- 2.5. 添加和更新实战
默认guns不支持添加headers的需要添加ax2
二、解决方案
2.1. 创建CSRF防御统一管理
package com.gblfy.sys.config.web.csrf;import com.gblfy.base.utils.SHACoderUtil;import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;/*** CSRF防御统一管理** @author gblfy* @date 2020-12-13*/
public final class CSRFTokenManager {/*** token令牌参数名*/static final String CSRF_PARAM_NAME = "cSRFToken";/*** 会话中存储令牌的位置(session中的csrfToken的key)*/public static final String CSRF_TOKEN_FOR_SESSION_ATTR_NAME = CSRFTokenManager.class.getName() + ".tokenval";public static String getTokenForSession(HttpSession session) {String token = null;//我不能允许一个会话中有多个令牌——在两个的情况下//尝试并发地初始化token令牌的请求// init the token concurrentlysynchronized (session) {token = (String) session.getAttribute(CSRF_TOKEN_FOR_SESSION_ATTR_NAME);if (null == token) {token = SHACoderUtil.encodeSHA256Hex(cn.hutool.core.lang.UUID.randomUUID().toString());session.setAttribute(CSRF_TOKEN_FOR_SESSION_ATTR_NAME, token);}}return token;}/*** Extracts the token value from the session** @param request* @return*/public static String getTokenFromRequest(HttpServletRequest request) {return request.getParameter(CSRF_PARAM_NAME);}private CSRFTokenManager() {}public static void main(String[] args) {System.out.println(CSRF_TOKEN_FOR_SESSION_ATTR_NAME);}
}
2.2. 创建csrfToken校验
package com.gblfy.sys.config.web.csrf;import com.gblfy.sys.core.exception.page.InvalidCSRFTokenException;
import org.springframework.stereotype.Component;import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;@Component
public class CsrfToken {/*** 校验CsrfToken是否合法** @param request* @param session*/public static void checkCsrfToken(HttpServletRequest request, HttpSession session) {String requestHeaderToken = request.getHeader("__RequestVerificationToken");String sessionCsrfToken = session.getAttribute(CSRFTokenManager.CSRF_TOKEN_FOR_SESSION_ATTR_NAME).toString();if (requestHeaderToken == null|| "".equals(requestHeaderToken)|| "".equals(sessionCsrfToken)|| sessionCsrfToken == null|| !requestHeaderToken.equals(sessionCsrfToken)) {throw new InvalidCSRFTokenException();}}
}
2.3. 加密工具类
<!--SHA256Hex加密--><dependency><groupId>commons-codec</groupId><artifactId>commons-codec</artifactId><version>1.13</version></dependency>
package com.gblfy.base.utils;import org.apache.commons.codec.digest.DigestUtils;
import org.springframework.stereotype.Component;@Component
public class SHACoderUtil {
/*** SHA256Hex加密** @param data 待加密数据* @return String 消息摘要* @throws Exception*/public static String encodeSHA256Hex(String data) {// 执行消息摘要return DigestUtils.sha256Hex(data);}public static void main(String[] args) throws Exception {String pasww = encodeSHA256Hex("");System.out.println("####"+pasww);}}
2.4. 查询实战
/*** 跳转到查看管理员列表的页面** @author gblfy* @Date 2018/12/24 22:43*/@RequestMapping("")public String index(Model model,HttpServletRequest request) {model.addAttribute(ConstDb.CSRF_TOKEN, CSRFTokenManager.getTokenForSession(request.getSession()));return PREFIX + "user.html";}
<input type="hidden" id="cSRFToken" value="${csrf}" name="cSRFToken">
var headers = {};headers['__RequestVerificationToken'] = $("#cSRFToken").val();// 渲染表格var tableResult = table.render({elem: '#' + MgrUser.tableId,url: Feng.ctxPath + '/mgr/list',headers:headers,page: true,height: "full-98",cellMinWidth: 100,toolbar: '<div>工具栏</div>',defaultToolbar: ['filter', 'print'],cols: MgrUser.initColumn()});
/*** 查询管理员列表** @author gblfy* @Date 2018/12/24 22:43*/@RequestMapping("/list")@Permission@ResponseBodypublic Object list(@RequestParam(required = false) String name,@RequestParam(required = false) String timeLimit,@RequestParam(required = false) Long deptId, HttpServletRequest request, HttpSession session) {//校验CsrfToken是否合法CsrfToken.checkCsrfToken(request,session);// ----------------------正常逻辑----------------------//拼接查询条件String beginTime = "";String endTime = "";if (ToolUtil.isNotEmpty(timeLimit)) {String[] split = timeLimit.split(" - ");beginTime = split[0];endTime = split[1];}if (ShiroKit.isAdmin()) {Page<Map<String, Object>> users = userService.selectUsers(null, name, beginTime, endTime, deptId);Page wrapped = new UserWrapper(users).wrap();return LayuiPageFactory.createPageInfo(wrapped);} else {DataScope dataScope = new DataScope(ShiroKit.getDeptDataScope());Page<Map<String, Object>> users = userService.selectUsers(dataScope, name, beginTime, endTime, deptId);Page wrapped = new UserWrapper(users).wrap();return LayuiPageFactory.createPageInfo(wrapped);}}
2.5. 添加和更新实战
/*** 跳转到查看管理员列表的页面** @author gblfy* @Date 2018/12/24 22:43*/@RequestMapping("/user_add")public String addView(Model model,HttpServletRequest request) {model.addAttribute(ConstDb.CSRF_TOKEN, CSRFTokenManager.getTokenForSession(request.getSession()));return PREFIX + "user_add.html";}/*** 跳转到编辑管理员页面** @author gblfy* @Date 2018/12/24 22:43*/@Permission@RequestMapping("/user_edit")public String userEdit(@RequestParam Long userId,Model model,HttpServletRequest request) {model.addAttribute(ConstDb.CSRF_TOKEN, CSRFTokenManager.getTokenForSession(request.getSession()));if (ToolUtil.isEmpty(userId)) {throw new ServiceException(BizExceptionEnum.REQUEST_NULL);}User user = this.userService.getById(userId);LogObjectHolder.me().set(user);return PREFIX + "user_edit.html";}
<input type="hidden" id="cSRFToken" value="${csrf}" name="cSRFToken">
layui.use(['layer', 'form', 'admin', 'laydate', 'ax', 'ax2'], function () {var $ = layui.jquery;var $ax = layui.ax;var $ax2 = layui.ax2;var form = layui.form;var admin = layui.admin;var laydate = layui.laydate;var layer = layui.layer;
var headers = {};headers['__RequestVerificationToken'] = $("#cSRFToken").val();// 表单提交事件form.on('submit(btnSubmit)', function (data) {var ajax = new $ax2(Feng.ctxPath + "/mgr/add", headers, function (data) {Feng.success("添加成功!");//传给上个页面,刷新table用admin.putTempData('formOk', true);//关掉对话框admin.closeThisDialog();}, function (data) {Feng.error("添加失败!" + data.responseJSON.message)});ajax.set(data.field);ajax.start();});
});
layui.define(['jquery'], function (exports) {var $ = layui.$;var $ax2 = function (url,headers,success, error) {this.url = url;this.type = "post";this.data = {};this.dataType = "json";this.async = false;this.success = success;this.error = error;this.headers = headers;};$ax2.prototype = {start: function () {var me = this;var result = "";if (this.url.indexOf("?") === -1) {this.url = this.url + "?jstime=" + new Date().getTime();} else {this.url = this.url + "&jstime=" + new Date().getTime();}$.ajax({type: me.type,url: me.url,dataType: me.dataType,async: me.async,data: me.data,headers: me.headers,beforeSend: function (data) {},success: function (data) {result = data;if (me.success !== undefined) {me.success(data);}},error: function (data) {if (me.error !== undefined) {me.error(data);}}});return result;},set: function (key, value) {if (typeof key === "object") {for (var i in key) {if (typeof i === "function")continue;this.data[i] = key[i];}} else {this.data[key] = (typeof value === "undefined") ? $("#" + key).val() : value;}return this;},setData: function (data) {this.data = data;return this;},clear: function () {this.data = {};return this;}};exports('ax2', $ax2);
});
/*** 添加管理员** @author gblfy* @Date 2018/12/24 22:44*/@RequestMapping("/add")@BussinessLog(value = "添加管理员", key = "account", dict = UserDict.class)@Permission(Const.ADMIN_NAME)@ResponseBodypublic ResponseData add(@Valid UserDto user, BindingResult result, HttpServletRequest request, HttpSession session) {//校验CsrfToken是否合法CsrfToken.checkCsrfToken(request,session);// ----------------------正常逻辑----------------------if (result.hasErrors()) {throw new ServiceException(BizExceptionEnum.REQUEST_NULL);}this.userService.addUser(user);return SUCCESS_TIP;}/*** 修改管理员** @author gblfy* @Date 2018/12/24 22:44*/@RequestMapping("/edit")@BussinessLog(value = "修改管理员", key = "account", dict = UserDict.class)@ResponseBodypublic ResponseData edit(@Valid UserDto user, BindingResult result, HttpServletRequest request, HttpSession session) {//校验CsrfToken是否合法CsrfToken.checkCsrfToken(request,session);// ----------------------正常逻辑----------------------if (result.hasErrors()) {throw new ServiceException(BizExceptionEnum.REQUEST_NULL);}this.userService.editUser(user);return SUCCESS_TIP;}