大家都知道shiro方法級,請求級保障是不錯的,但是對于對于具體的行級數(shù)據(jù)安全控制是比較無力的,但是我們總是需要用一些手段來保證數(shù)據(jù)級的安全,舉個比較簡單的說明,
有合法登錄A和B用戶,A用戶通過方法findById=A可以加載出自己的信息并修改密碼,這個時候用戶B可以通過findById=A也可以加載出A的信息,這樣簡單的入侵方式比較簡單,
只要使用編輯器改動下表單的提交值即可,如果嚴謹是沒事的,但是總有那么一些人不會那么嚴謹,所以經(jīng)常都是通過id直出直入查詢到數(shù)據(jù),導致用戶資料泄漏被修改,
那么問題來了,我們該如何防止這樣的低級攻擊呢?
下面我提供一個比較簡單的方案,希望拋磚引玉,如果有更好的方案請分享出來,互相學習
一般來說,我們更新,刪除或者查詢單個記錄都是需要一個唯一鍵,例如id?別人可以編輯這個id的值獲取其他記錄的信息,這個時候我們可以加一個認證值給請求路徑,防止只修改了id
即可認為是合法請求
下面上些代碼
- <a href="#" onclick="removeById('/cms/user/removeById.do?id=${v.id}&rsv_=<@key id="${v.id}" />');return false;" style="cursor: pointer;">刪除</a>
看到后面刪除的參數(shù)有一個rsv_,這個是認證值,如果單獨修改id的值,但是沒有修改出相應的rsv_值那是認為是非法請求,因為id和rsv_是配套,通過一定算法出來的關聯(lián)
而這里我的<@key id="${v.id}" /> 這個是我自定義的freemarker標簽,相信看過前面的文章也知道該如何配置使用,下面我展示下生成的rsv_標簽類
- package com.silvery.core.freemarker;
-
- import java.io.IOException;
- import java.util.Map;
-
- import com.silvery.utils.ShortLinkUtils;
-
- import freemarker.core.Environment;
- import freemarker.template.TemplateDirectiveBody;
- import freemarker.template.TemplateDirectiveModel;
- import freemarker.template.TemplateException;
- import freemarker.template.TemplateModel;
-
- /**
- *
- * FreeMarker自定義標簽,生成編號認證
- *
- * @author shadow
- *
- */
- public class KeyTag implements TemplateDirectiveModel {
-
- @SuppressWarnings("unchecked")
- public void execute(Environment env, Map params, TemplateModel[] loopVars, TemplateDirectiveBody directiveBody)
- throws TemplateException, IOException {
-
- Object id = params.get("id");
- validate(id, null);
-
- env.getOut().write(ShortLinkUtils.getSingleLink(id.toString()));
-
- }
-
- private void validate(Object id, Object body) throws TemplateException {
- if (id == null || id.toString().trim().equals("")) {
- throw new TemplateException("參數(shù)[id]不能為空", null);
- }
- }
-
- }
然后看我們的請求攔截器,如何判斷是否合法請求
- package com.silvery.core.spring.handler;
-
- import java.text.SimpleDateFormat;
- import java.util.Date;
-
- import javax.servlet.http.HttpServletRequest;
- import javax.servlet.http.HttpServletResponse;
-
- import org.slf4j.Logger;
- import org.slf4j.LoggerFactory;
- import org.springframework.web.servlet.HandlerInterceptor;
- import org.springframework.web.servlet.ModelAndView;
-
- import com.silvery.utils.ShortLinkUtils;
-
- public class SystemHandler implements HandlerInterceptor {
-
- private final static Logger log = LoggerFactory.getLogger(SystemHandler.class);
-
- @Override
- public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object obj, Exception e)
- throws Exception {
- }
-
- @Override
- public void postHandle(HttpServletRequest request, HttpServletResponse response, Object obj, ModelAndView view)
- throws Exception {
- }
-
- @Override
- public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object obj) throws Exception {
- return validateSafeRequest(request, response, obj);
- }
-
- /** 防止擅改數(shù)據(jù)提交 */
- private boolean validateSafeRequest(HttpServletRequest request, HttpServletResponse response, Object obj) {
- String newObj = request.getParameter("id");
- if (!isNull(newObj)) {
- String newToken = request.getParameter("rsv_");
- if (!isNull(newToken)) {
- if (ShortLinkUtils.getSingleLink(newObj).equals(newToken)) {
- return true;
- }
- }
- log.error(new StringBuffer().append(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date())).append(
- " [").append(obj).append("] ").append(" appear insecure request ").toString());
- return false;
- }
- return true;
- }
-
- private boolean isNull(String s) {
- if (s == null || s.length() <= 0) {
- return true;
- }
- return false;
- }
-
- }
這是spring-mvc的攔截器,當然你也可以用普通的filter,原理是一樣
大概流程就是這樣,相信大家都能理解,比較簡單,比較實用,請隨意噴,最多我去藍翔再深造下回來咯...