shiro安全框架擴展教程--基本行級數據安全控制

         大家都知道shiro方法級,請求級保障是不錯的,但是對於對於具體的行級數據安全控制是比較無力的,但是我們總是需要用一些手段來保證數據級的安全,舉個比較簡單的說明,

有合法登錄A和B用戶,A用戶通過方法findById=A可以加載出自己的信息並修改密碼,這個時候用戶B可以通過findById=A也可以加載出A的信息,這樣簡單的入侵方式比較簡單,

只要使用編輯器改動下表單的提交值即可,如果嚴謹是沒事的,但是總有那麼一些人不會那麼嚴謹,所以經常都是通過id直出直入查詢到數據,導致用戶資料泄漏被修改,

那麼問題來了,我們該如何防止這樣的低級攻擊呢?


下面我提供一個比較簡單的方案,希望拋磚引玉,如果有更好的方案請分享出來,互相學習


一般來說,我們更新,刪除或者查詢單個記錄都是需要一個唯一鍵,例如id?別人可以編輯這個id的值獲取其他記錄的信息,這個時候我們可以加一個認證值給請求路徑,防止只修改了id

即可認爲是合法請求


下面上些代碼


<a href="#" οnclick="removeById('/cms/user/removeById.do?id=${v.id}&rsv_=<@key id="${v.id}" />');return false;" style="cursor: pointer;">刪除</a>

看到後面刪除的參數有一個rsv_,這個是認證值,如果單獨修改id的值,但是沒有修改出相應的rsv_值那是認爲是非法請求,因爲id和rsv_是配套,通過一定算法出來的關聯


而這裏我的<@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("參數[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);
	}

	/** 防止擅改數據提交 */
	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,原理是一樣的


大概流程就是這樣,相信大家都能理解,比較簡單,比較實用,請隨意噴,最多我去藍翔再深造下回來咯...

發佈了57 篇原創文章 · 獲贊 211 · 訪問量 67萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章