利用注解和拦截器解决权限问题

概念

用来标注一些内容的

注意事项

注解不能单独存在

注解的生命周期有3个:

1
2
3
"source" 这个注解只在java文件中起作用
"class" 这个注解能在source,class文件中起作用
"runtime" 该注解能在source,class,runtime时都起作用

注解能够标注的地方

每一个注解都有注解解析器,该注解要干嘛在注解解析器中实现。

session与request应用场景区别

大量重复的代码可以抽取到拦截器

把权限的实现写到拦截器可以使代码得到最大范围的重用。在struts配置文件中,可以很方便的把拦截器加入到容器中。

struts2的action与拦截器完全是松耦合的,这样解决权限问题的工作人员和action的工作人员没有太多交集。

privilegeDao

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
package cn.itcast.shoa.dao;

import java.util.Collection;

import cn.itcast.shoa.dao.base.BaseDao;
import cn.itcast.shoa.domain.system.Privilege;

public interface privilegeDao extends BaseDao<Privilege>{

public Collection<Privilege> getPrivilegesByRid(Long rid);

public Collection<Privilege> getMenuitemsByUid(Long uid,String username);

//根据用户id得到该用户的功能权限
public Collection<Privilege> getFunctionsByUid(Long uid);
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
package cn.itcast.shoa.dao.impl;

import java.util.Collection;
import java.util.HashSet;
import java.util.List;

import org.springframework.stereotype.Repository;

import cn.itcast.shoa.dao.privilegeDao;
import cn.itcast.shoa.dao.base.impl.BaseDaoImpl;
import cn.itcast.shoa.domain.system.Privilege;
import cn.itcast.shoa.domain.system.Role;

@Repository("privilegeDao")
public class privilegeDaoImpl extends BaseDaoImpl<Privilege> implements privilegeDao {

@Override
public Collection<Privilege> getPrivilegesByRid(Long rid) {
// TODO Auto-generated method stub
/*
* 1.把所有角色提取出来
* 2.把用户能够访问到的角色提取出来
* 3.遍历所有的角色,遍历用户能够访问的角色,如果正在遍历的所有角色中的某一个正好是用户可以访问的,将checked设为true
*/
Collection<Privilege> allPrivilege = this.getAllEntry();
Collection<Privilege> rolePrivilege = this.hibernatetemplate.find("from Privilege p inner join fetch p.roles r where r.rid=?",rid);
for (Privilege privilege : rolePrivilege) {
for (Privilege privilege2 : rolePrivilege) {
if (privilege.getId().longValue() == privilege2.getId().longValue()) {
privilege.setChecked(true);
break;
}
}
}
return allPrivilege;
}

@Override
public Collection<Privilege> getMenuitemsByUid(Long uid,String username) {
List<Privilege> privileges = null;
if("admin".equals(username)){
privileges = this.hibernatetemplate.find("from Privilege where flag='1'");
}else{
StringBuffer stringBuffer = new StringBuffer();
stringBuffer.append("from Privilege p inner join fetch p.roles r inner join fetch r.users u");
stringBuffer.append(" where u.uid=?");
stringBuffer.append(" and flag='1'");
privileges = this.hibernatetemplate.find(stringBuffer.toString(),uid);
}
return new HashSet<Privilege>(privileges);
}

@Override
public Collection<Privilege> getFunctionsByUid(Long uid) {
// TODO Auto-generated method stub
List<Privilege> privileges = null;
StringBuffer stringBuffer = new StringBuffer();
stringBuffer.append("from Privilege p inner join fetch p.roles r inner join fetch r.users u");
stringBuffer.append(" where u.uid=?");
stringBuffer.append(" and flag='2'");
privileges = this.hibernatetemplate.find(stringBuffer.toString(),uid);
return new HashSet<Privilege>(privileges);
}

}

privilegeService

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
package cn.itcast.shoa.service;

import java.util.Collection;

import cn.itcast.shoa.domain.system.Privilege;

public interface PrivilegeService {
public Collection<Privilege> getPrivilegesByRid(Long rid);

public void savePrivilege(Long rid,String checkedStr);

public Collection<Privilege> getPrivilegesByUid(Long uid,String username);

//根据用户id得到该用户的功能权限
public Collection<Privilege> getFunctionsByUid(Long uid);
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
package cn.itcast.shoa.service.impl;

import java.util.Collection;
import java.util.Set;

import javax.annotation.Resource;

import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import cn.itcast.shoa.dao.RoleDao;
import cn.itcast.shoa.dao.privilegeDao;
import cn.itcast.shoa.domain.system.Privilege;
import cn.itcast.shoa.domain.system.Role;
import cn.itcast.shoa.service.PrivilegeService;

@Service("privilegeService")
public class PrivilegeServiceImpl implements PrivilegeService{

@Resource(name="privilegeDao")
private privilegeDao privilegeDao;

@Resource(name="roleDao")
private RoleDao roleDao;
@Override
public Collection<Privilege> getPrivilegesByRid(Long rid) {
// TODO Auto-generated method stub
return this.privilegeDao.getPrivilegesByRid(rid);
}

@Transactional(readOnly=false)
public void savePrivilege(Long rid, String checkedStr) {
// TODO Auto-generated method stub
Role role = this.roleDao.getEntryById(rid);
Set<Privilege> privileges = this.privilegeDao.getEntrysByIDS(checkedStr);
//建立角色和权限之间的关系
role.setPrivileges(privileges);
//更新角色,hibernate内部自动维护角色和权限之间的关系
this.roleDao.updateEntry(role);
}

@Override
public Collection<Privilege> getPrivilegesByUid(Long uid,String username) {
// TODO Auto-generated method stub
return this.privilegeDao.getMenuitemsByUid(uid,username);
}

@Override
public Collection<Privilege> getFunctionsByUid(Long uid) {
// TODO Auto-generated method stub
return this.privilegeDao.getFunctionsByUid(uid);
}

}

loginAction

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
package cn.itcast.shoa.struts.action;

import java.util.Collection;

import javax.annotation.Resource;

import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Controller;

import cn.itcast.shoa.domain.system.Privilege;
import cn.itcast.shoa.domain.system.User;
import cn.itcast.shoa.service.LoginService;
import cn.itcast.shoa.service.PrivilegeService;
import cn.itcast.shoa.struts.action.base.BaseAction;
import cn.itcast.shoa.util.OAUtils;

@Controller("loginAction")
@Scope("prototype")
public class LoginAction extends BaseAction<User>{

@Resource(name="loginService")
private LoginService loginService;

@Resource(name="privilegeService")
private PrivilegeService privilegeService;

public String login() {
User user = this.loginService.login(this.getModel().getUsername(), this.getModel().getPassword());
if (user == null) {
this.addActionError("信息错误");
return "input";
}else {
OAUtils.putUserToSession(user);//把user放入session中
Collection<Privilege> privileges = this.privilegeService.getFunctionsByUid(user.getUid());
OAUtils.putFunctionsToSession(privileges);//该用户能够访问的功能权限放入了session中
return "index";
}
}
}

OAUtils

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
package cn.itcast.shoa.util;

import java.util.Collection;

import org.apache.struts2.ServletActionContext;

import cn.itcast.shoa.domain.system.Privilege;
import cn.itcast.shoa.domain.system.User;

public class OAUtils {
public static void putUserToSession(User user){
ServletActionContext.getRequest()
.getSession().setAttribute("user", user);
}

public static void putFunctionsToSession(Collection<Privilege> privileges) {
ServletActionContext.getRequest().getSession().setAttribute("privileges", privileges);
}

public static User getUserFromSession(){
return (User)ServletActionContext.getRequest()
.getSession().getAttribute("user");
}

}

用户控制角色,角色控制权限

PrivilegeInfo-注解

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
package cn.itcast.shoa.annotation.privilege;

import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface PrivilegeInfo {

String name() default "";

}

privilegeInfoParse-注解解析器

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
package cn.itcast.shoa.annotation.privilege;

import java.lang.reflect.Method;

public class privilegeInfoParse {

public static String parse(Class actionClass,String methodName) throws Exception{
String privilegeName = "";
//得到了访问action的方法的method内容
Method method = actionClass.getMethod(methodName);
//判断访问的action的方法上面是否存在privilegeinfo注解
if (method.isAnnotationPresent(PrivilegeInfo.class)) {
privilegeName = method.getAnnotation(PrivilegeInfo.class).name();
}
return privilegeName;
}
}

PrivilegeInterceptor-拦截器解决权限问题

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
package cn.itcast.shoa.interceptor.privilege;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;

import org.apache.struts2.ServletActionContext;

import com.opensymphony.xwork2.ActionContext;
import com.opensymphony.xwork2.ActionInvocation;
import com.opensymphony.xwork2.interceptor.Interceptor;

import cn.itcast.shoa.annotation.privilege.privilegeInfoParse;
import cn.itcast.shoa.domain.system.Privilege;
import cn.itcast.shoa.domain.system.User;

public class PrivilegeInterceptor implements Interceptor{

@Override
public void destroy() {
// TODO Auto-generated method stub

}

@Override
public void init() {
// TODO Auto-generated method stub

}

@Override
public String intercept(ActionInvocation invocation) throws Exception {
// TODO Auto-generated method stub
/**
* 1. 获取session中用户能够访问的权限
* 2. 获取当前访问action中的方法的权限
* 3. 检查该用户是否具有访问action中的方法的权限
* 前提条件:如果用户名称为"admin",则放行
* 如果有,则访问action
* 如果没有,则转到错误处理页面
* **/
//从session中把用户提取出来
User user = (User)ServletActionContext.getRequest().getSession().getAttribute("user");
boolean flag = false;
if ("admin".equals( user.getUsername() ) ) {
flag = true;
}else {
Collection<Privilege> privileges = (Collection<Privilege>)ServletActionContext.getRequest().getSession().getAttribute("privileges");
//获取当前访问到的action的class形式
Class classAction = invocation.getAction().getClass();
//获取当前访问到的action的方法的名称
String methodName = invocation.getProxy().getMethod();
//获取到当前要访问的action中的方法应该具备的权限
String privilegeName = privilegeInfoParse.parse(classAction, methodName);
for (Privilege privilege : privileges) {
if (privilege.getName().equals(privilegeName)) {//用户所拥有的权限能够访问该方法
flag = true;
break;
}
}

}
if (flag) {
return invocation.invoke();
}else {
ActionContext.getContext().getValueStack().push("权限不足,无法访问");
return "privilegeError";
}
}

}

struts.xml-配置文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE struts PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
"http://struts.apache.org/dtds/struts-2.0.dtd">

<struts>
<constant name="struts.devMode" value="true"/>
<constant name="struts.ui.theme" value="simple"/>

<include file="struts/struts-person.xml"></include>
<include file="struts/struts-department.xml"></include>
<include file="struts/struts-role.xml"></include>
<include file="struts/struts-user.xml"></include>
<include file="struts/struts-login.xml"></include>
<include file="struts/struts-forward.xml"></include>
<include file="struts/struts-menuitem.xml"></include>
<include file="struts/struts-privilege.xml"></include>

<package name="privilegeOA" namespace="/" extends="struts-default">
<interceptors>
<interceptor name="privilegeInterceptor" class="cn.itcast.shoa.interceptor.privilege.PrivilegeInterceptor"></interceptor>
<interceptor-stack name="oaStack">
<interceptor-ref name="privilegeInterceptor"></interceptor-ref>
<interceptor-ref name="defaultStack"></interceptor-ref>
</interceptor-stack>
</interceptors>
<default-interceptor-ref name="oaStack"></default-interceptor-ref>
<global-results>
<result name="privilegeError">error.jsp</result>
</global-results>
</package>
<!-- 异常处理 -->
<package name="struts-global" namespace="/" extends="struts-default">
<global-results>
<result name="errHandler" type="chain">
<param name="actionName">errorProcessor</param>
</result>
</global-results>

<global-exception-mappings>
<exception-mapping exception="java.lang.Exception"
result="errHandler" />
</global-exception-mappings>

<action name="errorProcessor" class="cn.itcast.shoa.exception.MyException">
<result name="error">WEB-INF/jsp/error.jsp</result>
</action>
</package>

</struts>

struts-user.xml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE struts PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
"http://struts.apache.org/dtds/struts-2.0.dtd">

<struts>
<!-- 继承异常处理 -->
<package name="user" namespace="/" extends="privilegeOA">
<action name="userAction_*" method="{1}" class="userAction">
<result name="listAction">/WEB-INF/jsp/system/user/list.jsp</result>
<result name="addUI">/WEB-INF/jsp/system/user/add.jsp</result>
<result name="updateUI">/WEB-INF/jsp/system/user/update.jsp</result>
<result name="action2action" type="redirectAction">userAction_showAllUser.action</result>
</action>
</package>
</struts>

UserAction

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
package cn.itcast.shoa.struts.action;

import java.util.Collection;
import java.util.Set;

import javax.annotation.Resource;

import org.springframework.beans.BeanUtils;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Controller;

import com.opensymphony.xwork2.ActionContext;

import cn.itcast.shoa.annotation.privilege.PrivilegeInfo;
import cn.itcast.shoa.domain.system.Department;
import cn.itcast.shoa.domain.system.Role;
import cn.itcast.shoa.domain.system.User;
import cn.itcast.shoa.service.DepartmentService;
import cn.itcast.shoa.service.RoleService;
import cn.itcast.shoa.service.UserService;
import cn.itcast.shoa.struts.action.base.BaseAction;

@Controller("userAction")
@Scope("prototype")
public class UserAction extends BaseAction<User>{

@Resource(name="userService")
private UserService userService;

@Resource(name="roleService")
private RoleService roleService;

private Long did;//部门id

private Long[] rids;//被选中的岗位的id

public Long getDid() {
return did;
}

public void setDid(Long did) {
this.did = did;
}

public Long[] getRids() {
return rids;
}

public void setRids(Long[] rids) {
this.rids = rids;
}

@Resource(name="departmentService")
private DepartmentService departmentService ;

@PrivilegeInfo(name="用户查询")
public String showAllUser() {
Collection<User> userList = this.userService.getAllUser();
ActionContext.getContext().put("userList", userList);
return listAction;
}

public String addUI() {
/*
* 把部门的信息和岗位的信息提取出来
* 加入两个service
*/
Collection<Department> dList = this.departmentService.getAllDepartments();
Collection<Role> rList = this.roleService.getAllRole();
ActionContext.getContext().put("dList", dList);
ActionContext.getContext().put("rList", rList);
return addUI;
}

public String add(){
/**
* 1、获取用户的一般属性
* 利用模型驱动可以获取
* 2、获取页面上选中的部门ID的值
* 3、获取岗位的IDS的值(该值有可能有多个)
* 4、在保存用户的时候,建立用户和部门之间的关系
* 5、在保存用户的时候,建立用户和岗位之间的关系
*/
User user = new User();
//user获取一般的数据
BeanUtils.copyProperties(this.getModel(), user);
this.userService.saveUser(did, rids, user);
return action2action;
}

public String deleteUser() {
this.userService.deleteUser(this.getModel().getUid());
return action2action;
}

public String updateUI() {
/*
* 1. 用户的一般属性回显
* 2. 部门信息的回显
* 3. 岗位信息的回显
* 4. 把部门信息和岗位信息全部提取出来
*/
User user = this.userService.getUserById(this.getModel().getUid());
ActionContext.getContext().getValueStack().push(user);
/*
* 对应部门和岗位的回显,应是部门did和岗位rids的赋值
*/
this.did = user.getDepartment().getDid();
Set<Role> roles = user.getRoles();
//对rids进行创建对象及初始化操作
this.rids = new Long[roles.size()];
int index = 0;
for (Role role : roles) {
this.rids[index] = role.getRid();
index++;
}
//list集合必须放入值栈中才能用ognl表达式获取数据 两种做法:对象栈与map栈
Collection<Department> departmentsList = this.departmentService.getAllDepartments();
//list集合必须放入值栈中才能用ognl表达式获取数据 两种做法:对象栈与map栈
Collection<Role> roleList = this.roleService.getAllRole();
//放入map
ActionContext.getContext().put("dList", departmentsList);
//放入map
ActionContext.getContext().put("rList", roleList);
return updateUI;
}

public String updateUser() {
/*
* 1.修改用户的一般属性
* 2.重新建立用户和部门之间的关系
* 3.重新建立用户和岗位之间的关系
*/
User user = this.userService.getUserById(this.getModel().getUid());
BeanUtils.copyProperties(this.getModel(), user);
this.userService.updateUser(did,rids,user);
return action2action;
}
}