Struts2中基于Annotation的细粒度权限控制
权限控制是保护系统安全运行很重要的一扇门。在web应用里,仅仅隐藏url是不够的。由于web应用是以请求/响应为单位的,我 们的权限控制的粒度只有达到这个程度才能让全国人民放心。在java web开发的世界里,MVC框架的使用再平常不过,大都是将请求拦截后,控制器根据配置文件将请求转给某个函数来处理。下面看看在struts2中我们可 以用的几种方案:
1、在每个函数里进行权限校验
这主意实在是简单,缺点我就不说了~太多了~
2、在每个请求对应的Action的配置项里配置参数,用以标示访问此Action需要的权限,再用拦截器处理
以 前我这么做过,比方案1好很多,不过这注定你无法实现ZeroConfig。在ROR的促进下,约定优于配置渐渐深入人心。本人就极其反感大量的配置文 件。但是由于权限配置提到XML里配置,最大的好处就是我不必重新编译代码就能改变权限关联。不过情况下遇到需求变更,你会有一种宁可去改代码的冲动。
3、结合Java的Annotation和Struts2的拦截器控制权限
下面是上午没事写的一个示例:访问login.jsp,登录,功能有eat和drink,用户登陆后只能访问已授权的功能链接。
基本思想:对每个Action方法进行注解,并注入一个资源字符串,部署一个拦截器,在每个请求之前拦截一下,通过反射拿到所调用的方法及其注解,依此来进行权限校验。
优点:
简单、可行性高
不修改MVC框架配置文件
不影响Action内的业务逻辑
注解的原则之一就是不影响代码的运行,这也实现了本方案的可插拔性、独立性高
更高的可配置性
缺点:
不知道对性能影响如何
代码基本上都贴到下面了,不想细讲了,有兴趣的可以留言讨论,觉得我火星的就不要拍砖了,有需要eclipse工程源码的发邮件问我要shoru#163.com。

(1)Annotation相关
Access
1package com.shoru.access;
2
3import java.lang.annotation.ElementType;
4import java.lang.annotation.Retention;
5import java.lang.annotation.RetentionPolicy;
6import java.lang.annotation.Target;
7
8/** *//**
9 * 访问控制注解
10 * 该注解保留到运行时,针对方法使用,默认为BLOCK
11 * @author Shoru
12 * @version 0.1
13 */
14@Retention(RetentionPolicy.RUNTIME)
15@Target(ElementType.METHOD)
16public @interface Access {
17 String[] value() default { AccessOption.BLOCK };
18}
AccessOption
1package com.shoru.access;
2
3/** *//**
4 * 访问控制接口,定义默认的控制常量
5 * @author Shoru
6 * @version 0.1
7 */
8public interface AccessOption {
9 /** *//**
10 * 拦截访问
11 */
12 public static String BLOCK="block";
13 /** *//**
14 * 通过访问
15 */
16 public static String PASS="pass";
17 /** *//**
18 * 要求登录
19 */
20 public static String LOGIN="login";
21}
UserAccessOption
1package com.shoru.access;
2
3
4/** *//**
5 * 用户自定义控制接口,继承自AccessOption
6 * 可将系统权限全部定义到此处,格式为:权限名=资源名
7 * @author Shoru
8 * @see AccessOption
9 */
10public interface UserAccessOption extends AccessOption {
11 public static String EAT = "eat";
12 public static String DRINK = "drink";
13}
(2)Action类
AccessAction
1package com.shoru.access.action;
2
3import java.util.ArrayList;
4import java.util.List;
5
6import com.opensymphony.xwork2.Action;
7import com.opensymphony.xwork2.ActionContext;
8import com.shoru.access.Access;
9import com.shoru.access.UserAccessOption;
10
11public class AccessAction implements Action {
12 @Access
13 public String execute() throws Exception {
14 return SUCCESS;
15 }
16
17 @Access(UserAccessOption.PASS)
18 public String index() throws Exception {
19 /**//*
20 * 此处模拟权限的获取
21 */
22 List<String> accessPoints = new ArrayList<String>();
23 /**//*
24 * 赋予eat权限
25 */
26 accessPoints.add("eat");
27 ActionContext.getContext().getSession().put("access", accessPoints);
28 return SUCCESS;
29 }
30
31 @Access(UserAccessOption.DRINK)
32 public String drink() throws Exception {
33 return SUCCESS;
34 }
35
36 @Access( { UserAccessOption.EAT })
37 public String eat() throws Exception {
38 return SUCCESS;
39 }
40}
(3)拦截器
AccessInterceptor
1package com.shoru.access.interceptor;
2
3import java.lang.annotation.Annotation;
4import java.lang.reflect.Method;
5import java.util.List;
6
7import com.opensymphony.xwork2.ActionContext;
8import com.opensymphony.xwork2.ActionInvocation;
9import com.opensymphony.xwork2.interceptor.Interceptor;
10import com.opensymphony.xwork2.util.AnnotationUtils;
11import com.shoru.access.Access;
12import com.shoru.access.AccessOption;
13
14public class AccessInterceptor implements Interceptor {
15
16 private static final long serialVersionUID = -1066389312400000758L;
17
18 List<String> accessPoints = null;
19
20 public void init() {
21
22 }
23
24 public void destroy() {
25 accessPoints = null;
26 }
27
28 public String intercept(ActionInvocation invocation) throws Exception {
29 if (accessPoints == null) {
30 /**//*
31 * 获取权限列表
32 */
33 accessPoints = (List<String>) ActionContext.getContext()
34 .getSession().get("access");
35 }
36 /**//*
37 * 获取此次调用的方法名
38 */
39 String method = invocation.getProxy().getMethod();
40 /**//*
41 * 获取所有已注解方法
42 */
43 List<Method> methods = AnnotationUtils.findAnnotatedMethods(invocation
44 .getAction().getClass(), Access.class);
45 /**//*
46 * 迭代所有已注解方法
47 */
48 for (Method m : methods) {
49 if (m.getName().equals(method)) {
50 /**//*
51 * 获取被调用方法的注解
52 */
53 Annotation annotation = m.getAnnotation(Access.class);
54 /**//*
55 * 放过不需要校验权限列表的请求,e.g.登录、验证码
56 */
57 for (String s : ((Access) annotation).value()) {
58 if (s.equals(AccessOption.PASS)) {
59 return invocation.invoke();
60 }
61 }
62 /**//*
63 * 权限列表为空,返回登录
64 */
65 if (accessPoints == null) {
66 return AccessOption.LOGIN;
67 }
68 /**//*
69 * 迭代方法注解里的值,判断是否存在于权限列表中
70 */
71 for (String s : ((Access) annotation).value()) {
72 if (accessPoints.indexOf(s) != -1) {
73 /**//*
74 * 权限校验通过
75 */
76 return invocation.invoke();
77 }
78 }
79 }
80 }
81 /**//*
82 * 没有对方法进行注解或者权限校验不通过,拦截此次请求
83 */
84 return AccessOption.BLOCK;
85 }
86}
(4)struts.xml
struts.xml
1<?xml version="1.0" encoding="UTF-8"?>
2<!DOCTYPE struts PUBLIC
3 "-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
4 "http://struts.apache.org/dtds/struts-2.0.dtd">
5<struts>
6 <package name="access" extends="struts-default">
7 <interceptors>
8 <!-- 权限拦截器 -->
9 <interceptor name="access"
10 class="com.shoru.access.interceptor.AccessInterceptor"></interceptor>
11 <interceptor-stack name="my-default">
12 <interceptor-ref name="access"></interceptor-ref>
13 <interceptor-ref name="defaultStack"></interceptor-ref>
14 </interceptor-stack>
15 </interceptors>
16 <default-interceptor-ref name="my-default"></default-interceptor-ref>
17 <global-results>
18 <result name="block">/login.jsp</result>
19 <result name="login">/login.jsp</result>
20 </global-results>
21 <!-- Zero Config All Actions -->
22 <action name="*" class="com.shoru.access.action.AccessAction"
23 method="{1}">
24 <result>/{1}.jsp</result>
25 </action>
26
Struts2中基于Annotation的细粒度权限控制的更多相关文章
- Shiro入门之二 --------基于注解方式的权限控制与Ehcache缓存
一 基于注解方式的权限控制 首先, 在spring配置文件applicationContext.xml中配置自动代理和切面 <!-- 8配置自动代理 --> <bean cl ...
- 尝试asp.net mvc 基于controller action 方式权限控制方案可行性
微软在推出mvc框架不久,短短几年里,版本更新之快,真是大快人心,微软在这种优秀的框架上做了大量的精力投入,是值得赞同的,毕竟程序员驾驭在这种框架上,能够强力的精化代码,代码层次也更加优雅,扩展较为方 ...
- 一种基于annotation的Spring-mvc权限控制方法
简介 本文介绍一种采用annotation来对spring-mvc进行权限控制的方法. 通过枚举类来定义权限项. 将annotation标注到需要控制权限的spring-mvc方法上. 然后,在spr ...
- ASP.NET Core 实战:基于 Jwt Token 的权限控制全揭露
一.前言 在涉及到后端项目的开发中,如何实现对于用户权限的管控是需要我们首先考虑的,在实际开发过程中,我们可能会运用一些已经成熟的解决方案帮助我们实现这一功能,而在 Grapefruit.VuCore ...
- 尝试asp.net mvc 基于controller action 方式权限控制方案可行性(转载)
微软在推出mvc框架不久,短短几年里,版本更新之快,真是大快人心,微软在这种优秀的框架上做了大量的精力投入,是值得赞同的,毕竟程序员驾驭在这种框架上,能够强力的精化代码,代码层次也更加优雅,扩展较为方 ...
- Xianfeng轻量级Java中间件平台:基于RBAC模型实现权限控制的原理
首先,白话一下RBAC模型.RBAC是基于角色的访问控制(Role-Based Access Control)的简称.RBAC认为权限授权实际上是Who.What.How的问题.在RBAC模型中,wh ...
- Android中的安全与访问权限控制
Android是一个多进程系统,在这个系统中,应用程序(或者系统的部分)会在自己的进程中运行.系统和应用之间的安全性是通过Linux的facilities(工具,功能)在进程级别来强制实现的,比如会给 ...
- angular基于ui-router实现系统权限控制
前端去实现权限控制听起来有点扯淡(实际也有点扯淡),掩耳盗铃,主要是担心安全问题,但是如果在前后端分离的情况下,需要做一个带有权限控制的后台管理系统,angular基于ui-router应该怎么做呢? ...
- 基于SpringSecurity实现RBAC权限控制(待完善)
Spring Security是一个为企业应用系统提供声明式的安全访问控制功能,减少为了企业应用系统安全控制而编写的大量重复代码. 认证: spring security的原理就是使用很多的拦截器对U ...
随机推荐
- Objective-c基础学习
核心内容 标识号 OC语言中,对各种变量,方法和类等要素命名时使用的字符序列称为标识符. OC标识符命名规则标识符由字母,下划线“_”,美元符号“$”和数字组成,标识符必须以字母,下划线,美元符号开头 ...
- 老王Python培训视频教程(价值500元)【基础进阶项目篇 – 完整版】
老王Python培训视频教程(价值500元)[基础进阶项目篇 – 完整版] 教学大纲python基础篇1-25课时1.虚拟机安装ubuntu开发环境,第一个程序:hello python! (配置开发 ...
- Android强制弹出,隐藏输入法.
当我们弹出一个Dialog时候,如果这个Dialog需要输入数据,然后确定后又需要关闭输入法,一般系统的hide,跟show方法总会有各种问题,最霸道的解决方法就是写一个定时器,定时弹出或者关闭输入法 ...
- LeetCode 笔记23 Best Time to Buy and Sell Stock III
Best Time to Buy and Sell Stock III Say you have an array for which the ith element is the price of ...
- 学习笔记——Maven超级POM
2014-07-04:更新如何在安装程序中找到超级pom文件.Maven有一个超级POM,所有的POM均继承此文件.你可以使用解压工具打开jar文件$M2_HOME/lib/maven-model-b ...
- Mysqli基础知识
相信原来在开始学习php的时候,很多人使用的数据库首选MySQL,连接数据库的扩展首选mysql扩展,但随着php版本的提高,mysql扩展正逐渐被mysqli和PDO所取代.正如使用mysql函数时 ...
- VS2008+GDI实现多幅图像的GIF动画制作
相信很多朋友和我一样,经常由于这或那的原因,需制作一些特定格式的图像.如开发过程中需要给菜单.工具条及按钮等添加对应的图形标识,通过代码或资源导入方式加载这些图像时往往会有较高的格式要求. 比如,为按 ...
- VMware打卡虚拟机提示“此虚拟机可能已被复制或移动”
使用VMware打开虚拟机时出现下图的页面,我来解释一下这三个选项按钮的区别与作用. "我已移动虚拟机" //表示打开后的虚拟的网卡的mac地址不变,如果复制本地的,同时开 ...
- css的垂直居中
请先看博客:http://www.jb51.net/css/39629.html
- EntityFramework_MVC4中EF5 新手入门教程之四 ---4.在EF中创建更复杂的数据模型
在以前的教程你曾与一个简单的数据模型,由三个实体组成.在本教程中,您将添加更多的实体和关系,并通过指定格式. 验证和数据库映射规则,您将自定义数据模型.你会看到自定义的数据模型的两种方式: 通过添加属 ...