shiro安全框架扩展教程--基本行级数据安全控制

         大家都知道shiro方法级,请求级保障是不错的,但是对于对于具体的行级数据安全控制是比较无力的,但是我们总是需要用一些手段来保证数据级的安全,举个比较简单的说明,

有合法登录A和B用户,A用户通过方法findById=A可以加载出自己的信息并修改密码,这个时候用户B可以通过findById=A也可以加载出A的信息,这样简单的入侵方式比较简单,

只要使用编辑器改动下表单的提交值即可,如果严谨是没事的,但是总有那么一些人不会那么严谨,所以经常都是通过id直出直入查询到数据,导致用户资料泄漏被修改,

那么问题来了,我们该如何防止这样的低级攻击呢?


下面我提供一个比较简单的方案,希望抛砖引玉,如果有更好的方案请分享出来,互相学习


一般来说,我们更新,删除或者查询单个记录都是需要一个唯一键,例如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>

看到后面删除的参数有一个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,原理是一样的


大概流程就是这样,相信大家都能理解,比较简单,比较实用,请随意喷,最多我去蓝翔再深造下回来咯...

你可能感兴趣的:(java,框架,shiro,开源,安全)