权限控制(粗颗粒+细颗粒)

1 粗颗粒度权限控制(使用过滤器完成)

分析:

精确到Session的权限控制(判断Session是否存在)

使用过滤器完成粗颗粒的权限控制,如果Session不存在就跳转到首页,如果存在可以通过URL链接访问到对应的操作。

第一步:定义一个过滤器:

public class SystemFilter implements Filter {

/**web容器启动的时候,执行的方法*/

//存放没有Session之前,需要放行的连接

List<String> list = new ArrayList<String>();

public void init(FilterConfig config) throws ServletException {

list.add("/index.jsp");

        list.add("/image.jsp");

        list.add("/system/elecMenuAction_menuHome.do");

}

/**每次访问URL连接的时候,先执行过滤器的doFilter的方法*/

public void doFilter(ServletRequest req, ServletResponse res,

FilterChain chain) throws IOException, ServletException {

HttpServletRequest request = (HttpServletRequest) req;

HttpServletResponse response = (HttpServletResponse) res;

//获取访问的连接地址

String path = request.getServletPath();

//在访问首页index.jsp页面之前,先从Cookie中获取name,password的值,并显示在页面上(完成记住我)

this.forwordIndexPage(path,request);

//如果访问的路径path包含在放行的List的存放的连接的时候,此时需要放行

if(list.contains(path)){

            chain.doFilter(request, response);

            return;

        }

        //获取用户登录的Session

        ElecUser elecUser = (ElecUser)request.getSession().getAttribute("globle_user");

        //放行

        if(elecUser!=null){

            chain.doFilter(request, response);

            return;

        }

        //重定向到登录页面

        response.sendRedirect(request.getContextPath()+"/index.jsp");

}

/**销毁*/

public void destroy() {

}

/**在访问首页index.jsp页面之前,先从Cookie中获取name,password的值,并显示在页面上(完成记住我)*/

private void forwordIndexPage(String path, HttpServletRequest request) {

if(path!=null && path.equals("/index.jsp")){

String name = "";

String password = "";

String checked = "";

Cookie [] cookies = request.getCookies();

if(cookies!=null && cookies.length>0){

for(Cookie cookie:cookies){

if(cookie.getName().equals("name")){

name = cookie.getValue();

/**

* 如果name出现中文,对中文进行解码

*/

try {

name = URLDecoder.decode(name, "UTF-8");

} catch (UnsupportedEncodingException e) {

e.printStackTrace();

}

checked = "checked";

}

if(cookie.getName().equals("password")){

password = cookie.getValue();

}

}

}

request.setAttribute("name", name);

request.setAttribute("password", password);

request.setAttribute("checked", checked);

}

}

}

第二步:在web容器中添加对应的过滤器:

<!-- 自定义过滤器,要求添加到struts2过滤器的前面 -->

<filter>

<filter-name>SystemFilter</filter-name>

<filter-class>cn.itcast.elec.util.SystemFilter</filter-class>

</filter>

<filter-mapping>

<filter-name>SystemFilter</filter-name>

<url-pattern>*.do</url-pattern>

<url-pattern>*.jsp</url-pattern>

</filter-mapping>

问题:不够友好,访问链接,最好提示【非法操作,系统将会5秒后跳转到登录页面】

修改过滤器类中的操作:

(1)在过滤器中的init方法中添加2个放行的连接:

list.add("/error.jsp");

list.add("/system/elecMenuAction_logout.do");

(2)在doFilter的方法重定向到error.jsp

将:

//重定向到登录页面

response.sendRedirect(request.getContextPath()+"/index.jsp");

修改成:

//重定向到error.jsp(5秒跳转到登录名页面)

response.sendRedirect(request.getContextPath()+"/error.jsp");

(3)error.jsp的内容:

<script>

var i=6;

var t;

function showTimer(){

if(i==0){//如果秒数为0的话,清除t,防止一直调用函数,对于反应慢的机器可能实现不了跳转到的效果,所以要清除掉 setInterval()

parent.location.href="${pageContext.request.contextPath }/system/elecMenuAction_logout.do";

window.clearInterval(t);

}else{

i = i - 1 ;

// 秒数减少并插入 timer 层中

document.getElementById("timer").innerHTML= i+"秒";

}

}

// 每隔一秒钟调用一次函数 showTimer()

t = window.setInterval(showTimer,1000);

</script>

注意:Session不应该在服务器一直不清空,如果Session过多,会导致Session压力大,系统变慢,于是要求10分钟如果不操作系统,将Session自动清空。在web.xml中配置

<session-config>

<session-timeout>10</session-timeout>

</session-config>

粗颗粒的权限控制的面试:

使用过滤器

在过滤器中定义放行的连接,因为不是每个操作都会存在Session

在过滤器中获取登录后存放的Session,如果Session不为空,则放行,即可以操作定义的业务功能,如果Session为空,则跳转到登录页面。

控制访问的系统必须要存在Session

2  细颗粒权限控制(使用struts2的拦截器)

/**
* 自定义注解
*/
//被这个注解修饰的注解,利用反射,将其他的注解读取出来
@Retention(RetentionPolicy.RUNTIME)
public @interface AnnotationLimit {
String mid();//权限的code
String pid();//父级权限的code
}

public class ErrorAndLimitInterceptor extends MethodFilterInterceptor {

/**拦截器*/
@Override
protected String doIntercept(ActionInvocation actioninvocation) throws Exception {
//把自定义错误信息 放置到request中
HttpServletRequest request = (HttpServletRequest) actioninvocation
.getInvocationContext().get(StrutsStatics.HTTP_REQUEST);
try {
//获取请求的action对象
Object action = actioninvocation.getAction();
//获取请求的方法的名称
String methodName = actioninvocation.getProxy().getMethod();
//获取action中的方法的封装类(action中的方法没有参数)
Method method = action.getClass().getMethod(methodName, null);
// Action的返回值
String result = null;

//在完成跳转Action之前完成细颗粒权限控制,控制Action的每个方法
//检查注解,是否可以操作权限的URL
//boolean flag = isCheckLimit(request,method);
if(true){
// 运行被拦截的Action,期间如果发生异常会被catch住
result = actioninvocation.invoke();
}
else{
request.setAttribute("errorMsg", "对不起!您没有权限操作此功能!");
return "errorMsg";
}
return result;
} catch (Exception e) {
/**
* 处理异常
*/
String errorMsg = "出现错误信息,请查看日志!";
//通过instanceof判断到底是什么异常类型
if (e instanceof RuntimeException) {
//未知的运行时异常
RuntimeException re = (RuntimeException) e;
//re.printStackTrace();
errorMsg = re.getMessage().trim();
}
/**
* 发送错误消息到页面
*/
request.setAttribute("errorMsg", errorMsg);

/**
* log4j记录日志
*/
Log log = LogFactory
.getLog(actioninvocation.getAction().getClass());
log.error(errorMsg, e);
return "errorMsg";
}// ...end of catch
}

/**验证细颗粒权限控制*/
public boolean isCheckLimit(HttpServletRequest request, Method method) {
if(method == null){
return false;
}
//获取当前的登陆用户
ElecUser elecUser = (ElecUser)request.getSession().getAttribute("globle_user");
if(elecUser == null){
return false;
}

//获取当前登陆用户的角色(一个用户可以对应多个角色)
Hashtable<String, String> ht = (Hashtable)request.getSession().getAttribute("globle_role");
if(ht == null){
return false;
}
//处理注解,判断方法上是否存在注解(注解的名称为:AnnotationLimit)
/*
* 例如:
* @AnnotationLimit(mid="aa",pid="0")
public String home(){
*/
boolean isAnnotationPresent = method.isAnnotationPresent(AnnotationLimit.class);

//不存在注解(此时不能操作该方法)
if(!isAnnotationPresent){
return false;
}

//存在注解(调用注解)
AnnotationLimit limit = method.getAnnotation(AnnotationLimit.class);

//获取注解上的值
String mid = limit.mid(); //权限子模块名称
String pid = limit.pid(); //权限父操作名称

/**
* 如果登陆用户的角色id+注解上的@AnnotationLimit(mid="aa",pid="0")
* * 在elec_role_popedom表中存在 flag=true,此时可以访问Action的方法;
* * 在elec_role_popedom表中不存在 flag=false,此时不能访问Action的方法;
*/
boolean flag = false;
//拦截器中加载spring容器,从而获取Service类,使用Service类查询对应的用户信息
WebApplicationContext wac = WebApplicationContextUtils.getWebApplicationContext(request.getSession().getServletContext());
IElecRoleService elecRoleService = (IElecRoleService)wac.getBean(IElecRoleService.SERVICE_NAME);
//遍历角色ID
if(ht!=null && ht.size()>0){
for(Iterator<Entry<String, String>> ite = ht.entrySet().iterator();ite.hasNext();){
Entry<String, String> entry = ite.next();
//获取角色ID
String roleID = entry.getKey();
flag = elecRoleService.findRolePopedomByID(roleID, mid, pid);
if(flag){
break;
}
}
}
return flag;
}

问题:为什么在struts2的拦截器中都要使用roleID,mid,pid去查询一遍数据库,而为什么不从Session中获取mid的值和注解上定义的mid的值进行比较呢?

回答:此时不安全,如果盗用账户,登录系统(一定有Session),即可以操作每一个执行的方法。但是由于挂失后,数据库存放的数据发生变化,操作每一个功能之前都会先查询权限,这样查询才能保证数据安全。

细颗粒的权限控制的面试:

使用struts2的拦截器

定义一个注解(mid和pid),对应权限code和父级权限的code,将注解添加到Action类中方法的上面

每个Action类的方法上添加注解(mid=””,pid=””),表示方法的惟一标识(即该方法所具有的权限)

在struts2的拦截器中,从Session中获取角色ID,获取Action类方法上的注解(mid和pid),使用角色ID,mid和pid查询角色权限表,判断当前用户是否可以操作该方法。

时间: 2024-12-15 04:48:07

权限控制(粗颗粒+细颗粒)的相关文章

粗颗粒度权限控制(使用过滤器完成)

分析: 精确到Session的权限控制(判断Session是否存在) 使用过滤器完成粗颗粒的权限控制,如果Session不存在就跳转到首页,如果存在可以通过URL链接访问到对应的操作. 第一步:定义一个过滤器: 1 public class SystemFilter implements Filter { 2 3 /**web容器启动的时候,执行的方法*/ 4 //存放没有Session之前,需要放行的连接 5 List<String> list = new ArrayList<Stri

角色、权限、账户的概念理解-非常全的理论讲解权限控制

组织模型   资源模型  操作模型 谁能够执行哪些操作    执行资源的范围 资源概念资源就是想要的到的最终物质,我们可以给每一个资源定义一个权限,也可以给某一类资源定义一个权限 权限概念权限是对资源的一种保护访问.用户要访问A资源前提是用户必须有A资源的访问权限. 角色概念实事上我们不会直接把权限赋予给用户,而是通过角色来赋予给用户,因为用户拥有某一种权限是因为用户扮演着某一种角色.A 是 个经理,他管理着B公司,他拥有b,c,d的权限.实际是不是A有这个权限,而是因为Abo是经理.因为经理拥

rbac 权限控制

RBAC 的控制,大致是通过将角色的权限控制,来控制用户的权限. 需要构建的表为 用户表(user) ,角色表(role),节点表(node),三张主表 , 节点表内记录的是所有的权限和方法. 2张关联表,是为了关联3张数据表的,分别未 角色用户表(user_role),角色权限表(role_node),也可将两张表写成字段分别加入到用户表和权限表内; 废话不多说看下,键表语句如下 用户表: CREATE TABLE `wj_admin` ( `id` int(11) NOT NULL AUTO

译-BMC Remedy Action Request System权限控制概述

原文链接:Access control overview 说明: BMC Remedy Action Request System是BMC ITSM产品平台,简称AR 或者Remedy,可实现基于ITIL标准的整个IT管理流程的实施定制.该平台可实现多种权限级别的管理,包括人员.组.角色,以及表.字段.行级别等.本文可以用作其他对权限要求比较精细的系统参考. 为了便于理解,部分名词翻译如下: Server:服务器Form (or table):表单Field (or column):字段Acti

基于MVC4+EasyUI的Web开发框架形成之旅--权限控制

我在上一篇随笔<基于MVC4+EasyUI的Web开发框架形成之旅--框架总体界面介绍>中大概介绍了基于MVC的Web开发框架的权限控制总体思路.其中的权限控制就是分为"用户登录身份验证"."控制器方法权限控制"."界面元素权限控制"三种控制方式,可以为Web开发框架本身提供了很好用户访问控制和权限控制,使得用户界面呈现菜单.Web界面的按钮和内容.Action的提交控制,均能在总体权限功能分配和控制之下. 本篇文章主要细化这三个方面

Orchard 之:Widget,兼看 Layer 在权限控制中的作用

一:Widget 可以理解为控件,可以直接被页面所引用.行为类似与分部页面,比如,我们可以创建一个 商品列表 Widget,然后这个 Widget 就可以被很多页面所引用. 理解 Widget 这个概念,我们不得不理解另外两个概念: 1:Layer Orchard 默认有这么几个层,Default.Authenticated.Anonymous.Disabled.TheHomepage.Layer 用于承载什么时候 Widget 将会被展现,这么讲大家一定觉得很抽象,其实 Layer 存在的意义

SpringMVC + Mybatis + SpringSecurity(权限控制到方法按钮) + Rest(服务) + Webservice(服务) + Quartz(定时调度)+ Lucene(搜索引擎) + HTML5 bootstrap + Maven项目构建绝对开源平台

框架整合: Springmvc + Mybatis + Shiro(权限) + REST(服务) + WebService(服务) + JMS(消息) + Lucene(搜搜引擎) + Quartz(定时调度) + Bootstrap Html5(支持PC.IOS.Android) 需要源码请加Q:3121026417   此处[源码获取地址] 框架简介: 项目Maven构建,真实大型互联网架构,做到高并发,大数据处理,整个项目使用定制化服务思想,提供模块化.服务化.原子化的方案,将功能模块进行

CloudStack API访问权限控制

在我写开始之前,请先看下CS中国社区的一篇文章http://www.cloudstack-china.org/2012/12/1465.html,在第1点里讲了关于权限级别,command属性文件位置等问题.不过4.3现在的除了command.properties外,作者提到的其它properties文件现在好像都没有了,而且command里面现在形如***command=15,"="后面不再有处理请求命令的类. API请求由ApiServlet拦截后,会调用verifyRequest

使用JavaEE的ServerAuthModule模块和web.xml进行相应配置,实现对用户的权限控制

ServerAuthModule这里不细说,可以自行百度. 重点在注释: <!-- 给web-app划分角色 --> <security-role> <role-name>spx.main</role-name> </security-role> <security-role> <role-name>spx.user</role-name> </security-role> <!-- 只有配置