您的位置:首页 > 运维架构 > 网站架构

2017年9月3日 实现网站的权限管理

2017-09-05 16:45 507 查看
  现在各个企业管理网站对登录的账号都要进行权限管理,并且相当重要,每个账号登录进去所能看到的东西大不相同,下面是实现该功能的一个的一种方法。

 需求:

权限:权限是使用者操作系统中功能模块的能力,如“角色管理”模块、“资费管 理”模块和“账单管理”模块等。通过指定权限,可将使用者的操作限定在指定的 范围内,以保证操作的安全。

例如,一个使用者拥有“资费管理”权限,表示该使 用者可以操作“资费管理”模块,以执行资费管理的操作。权限由 NetCTOSS 系 统内置,使用者不可以进行修改。

使用者对本系统的各功能模块的访问都是受权限 控制的,因此,权限决定了使用者可以执行的操作。

角色:角色是多种权限的集合,可通过授予使用者某种角色,以简化权限的管理。 比如,角色“账号管理员”同时具有“帐务账号”模块和“业务账号”模块的权限。

如果设置某使用者的角色为“账号管理员”,则意味着该使用者可以同时操作“帐 务账号“和”业务账号“模块









 

 准备工作:

Step1、将权限等级权限角色等信息录入数据库:





1 --模块表
2 create table module_info(
3         module_id     number(4) constraint module_info_id_pk primary key,
4         name         varchar2(50) not null
5 );
6
7 create sequence module_seq start with 100;
8
9 --角色表
10 create table role_info(
11         role_id        number(4)    constraint role_info_id_pk primary key,
12         name    varchar2(50)     not null
13 );
14
15 create sequence role_seq start with 1000;
16
17 --角色模块表
18 create table role_module(
19         role_id     number(4) not null,
20          module_id   number(4) not null,
21       constraint role_module_pk primary key(role_id,module_id)
22 );
23
24
25
26 --管理员表
27 create table admin_info(
28        admin_id     number(8) primary key not null,
29        admin_code     varchar2(30) not null,
30        password     varchar2(30) not null,
31        name         varchar2(30) not null,
32        telephone     varchar2(15),
33        email         varchar2(50),
34        enrolldate     date default sysdate not null
35 );
36
37 create sequence admin_seq start with 10000;
38
39
40 --管理员角色表
41 create table admin_role(
42         admin_id    number(8) not null,
43           role_id        number(4) not null,
44       constraint admin_role_pk primary key(admin_id,role_id)
45 );
46
47
48
49 --模块表
50 insert into MODULE_INFO values(1,'角色管理');
51 insert into MODULE_INFO values(2,'管理员');
52 insert into MODULE_INFO values(3,'资费管理');
53 insert into MODULE_INFO values(4,'账务账号');
54 insert into MODULE_INFO values(5,'业务账号');
55 insert into MODULE_INFO values(6,'账单管理');
56 insert into MODULE_INFO values(7,'报表');
57 commit;
58 --角色表
59 insert into role_info values(100,'管理员');
60 insert into role_info values(200,'营业员');
61 insert into role_info values(300,'经理');
62 insert into role_info values(400,'aaa');
63 insert into role_info values(500,'bbb');
64 insert into role_info values(600,'ccc');
65 commit;
66 --角色模块表
67 insert into role_module values(100,1);
68 insert into role_module values(100,2);
69 insert into role_module values(200,3);
70 insert into role_module values(200,4);
71 insert into role_module values(200,5);
72 insert into role_module values(200,6);
73 insert into role_module values(300,7);
74 commit;
75 --管理员表
76 insert into admin_info values(2000,'admin','123','ADMIN','123456789','admin@tarena.com.cn',sysdate);
77 insert into admin_info values(3000,'zhangfei','123','ZhangFei','123456789','zhangfei@tarena.com.cn',sysdate);
78 insert into admin_info values(4000,'liubei','123','LiuBei','123456789','liubei@tarena.com.cn',sysdate);
79 insert into admin_info values(5000,'caocao','123','CaoCao','123456789','caocao@tarena.com.cn',sysdate);
80 insert into admin_info values(6000,'aaa','123','AAA','123456789','aaa@tarena.com.cn',sysdate);
81 insert into admin_info values(7000,'bbb','123','BBB','123456789','bbb@tarena.com.cn',sysdate);
82 commit;
83 --管理员角色表
84 insert into admin_role values(2000,100);
85 insert into admin_role values(3000,200);
86 insert into admin_role values(4000,300);
87 insert into admin_role values(5000,100);
88 insert into admin_role values(5000,200);
89 insert into admin_role values(5000,300);


点+号查看
 Step2、连接数据库:





1 #db connection parameters
2 driver=oracle.jdbc.driver.OracleDriver
3 url=jdbc:oracle:thin:@176.217.20.254:1521:tarena
4 user=gg2014
5 password=gg2014
6 #datasource parameters
7 initsize=1
8 maxsize=3


数据库登录信息





1 <util:properties  location="classpath:jdbc.properties"/>
2
3     <!-- 定义数据源 -->
4     <bean
5         class="org.apache.commons.dbcp.BasicDataSource"
6         destroy-method="close">
7         <property name="url" value="#{jdbc.url}"/>
8         <property name="driverClassName" value="#{jdbc.driver}"/>
9         <property name="username" value="#{jdbc.user}"/>
10         <property name="password" value="#{jdbc.password}"/>
11     </bean>


xml配置文件中设置
Step3、其他xml文件中的设置(包含拦截器等):

1 <bean  class="org.mybatis.spring.SqlSessionFactoryBean">
2       <property name="dataSource" ref="ds" />
3       <property name="mapperLocations" value="classpath:com/tarena/entity/*.xml"/>
4     </bean>
5
6     <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
7        <property name="basePackage" value="com.tarena.dao" />
8        <property name="annotationClass"
9            value="com.tarena.annotation.MyBatisRepository"/>
10     </bean>
11
12     <context:component-scan base-package="com.tarena" />
13
14     <!-- 支持MVC注解 -->
15     <mvc:annotation-driven />
16
17     <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
18         <property name="prefix" value="/WEB-INF/"/>
19         <property name="suffix" value=".jsp"/>
20     </bean>
21
22     <!-- 注册拦截器 -->
23     <mvc:interceptors>
24         <!-- 登录检查拦截器 -->
25         <mvc:interceptor>
26             <mvc:mapping path="/**"/>
27             <mvc:exclude-mapping path="/login/toLogin.do"/>
28             <mvc:exclude-mapping path="/login/login.do"/>
29             <mvc:exclude-mapping path="/login/createImage.do"/>
30             <bean class="com.tarena.interceptor.LoginInterceptor"/>
31         </mvc:interceptor>
32         <!-- 判断当前模块拦截器 -->
33         <mvc:interceptor>
34             <mvc:mapping path="/**"/>
35             <bean class="com.tarena.interceptor.CurrentModuleInterceptor"/>
36         </mvc:interceptor>
37         <!-- 权限检查拦截器 -->
38         <mvc:interceptor>
39             <mvc:mapping path="/**"/>
40             <mvc:exclude-mapping path="/login/*"/>
41             <bean class="com.tarena.interceptor.CheckModuleInterceptor"/>
42         </mvc:interceptor>
43     </mvc:interceptors>
44
45     <!-- 开启AOP注解扫描 -->
46     <aop:aspectj-autoproxy proxy-target-class="true"/>
47
48     <!-- 处理异常 -->
49     <bean class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver">
50         <property name="exceptionMappings">
51             <props>
52                  <prop key="java.lang.Exception">main/error</prop>
53             </props>
54         </property>
55     </bean>
56
57     <!-- 声明式事务 -->
58     <bean
59         class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
60         <property name="dataSource" ref="ds" />
61     </bean>
62     <tx:advice  transaction-manager="txManager">
63         <tx:attributes>
64             <tx:method name="find*" read-only="true" />
65             <tx:method name="to*" read-only="true" />
66             <tx:method name="add*" propagation="REQUIRED" rollback-for="java.lang.Exception"/>
67             <tx:method name="update*" propagation="REQUIRED" rollback-for="java.lang.Exception"/>
68             <tx:method name="delete*" propagation="REQUIRED" rollback-for="java.lang.Exception"/>
69         </tx:attributes>
70     </tx:advice>
71     <aop:config proxy-target-class="true">
72         <aop:advisor advice-ref="txAdvice" pointcut="within(com.tarena.controller..*)" />
73     </aop:config>


Step4、写实体类,一个登录的账号信息,一个是权限的名称及对应编号





1 package com.tarena.entity;
2
3 import java.sql.Timestamp;
4 import java.util.List;
5
6 public class Admin {
7
8     private Integer admin_id;
9     private String admin_code;
10     private String password;
11     private String name;
12     private String telephone;
13     private String email;
14     private Timestamp enrolldate;
15
16     private List<Role> roles;
17     private List<Integer> roleIds;
18
19     public Integer getAdmin_id() {
20         return admin_id;
21     }
22
23     public void setAdmin_id(Integer admin_id) {
24         this.admin_id = admin_id;
25     }
26
27     public List<Role> getRoles() {
28         return roles;
29     }
30
31     public void setRoles(List<Role> roles) {
32         this.roles = roles;
33     }
34
35     public List<Integer> getRoleIds() {
36         return roleIds;
37     }
38
39     public void setRoleIds(List<Integer> roleIds) {
40         this.roleIds = roleIds;
41     }
42
43     public String getAdmin_code() {
44         return admin_code;
45     }
46
47     public void setAdmin_code(String admin_code) {
48         this.admin_code = admin_code;
49     }
50
51     public String getPassword() {
52         return password;
53     }
54
55     public void setPassword(String password) {
56         this.password = password;
57     }
58
59     public String getName() {
60         return name;
61     }
62
63     public void setName(String name) {
64         this.name = name;
65     }
66
67     public String getTelephone() {
68         return telephone;
69     }
70
71     public void setTelephone(String telephone) {
72         this.telephone = telephone;
73     }
74
75     public String getEmail() {
76         return email;
77     }
78
79     public void setEmail(String email) {
80         this.email = email;
81     }
82
83     public Timestamp getEnrolldate() {
84         return enrolldate;
85     }
86
87     public void setEnrolldate(Timestamp enrolldate) {
88         this.enrolldate = enrolldate;
89     }
90
91 }


账号信息





package com.tarena.entity;

public class Module {

private Integer module_id;
private String name;

public Integer getModule_id() {
return module_id;
}

public void setModule_id(Integer module_id) {
this.module_id = module_id;
}

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

}


权限模块
Step5、编写DAO的接口

package com.tarena.dao;

import java.util.List;
import java.util.Map;

import com.tarena.annotation.MyBatisRepository;
import com.tarena.entity.Admin;
import com.tarena.entity.Module;
import com.tarena.entity.page.Page;

@MyBatisRepository
public interface AdminDao {

List<Module> findModulesByAdmin(int adminId);

}


Step6、编写实现该接口的SQL语句

1 <?xml version="1.0" encoding="UTF-8" ?>
2 <!DOCTYPE mapper PUBLIC "-//ibatis.apache.org//DTD Mapper 3.0//EN"
3  "http://ibatis.apache.org/dtd/ibatis-3-mapper.dtd">
4
5 <mapper namespace="com.tarena.dao.AdminDao">
6
7
8     <select
9         parameterType="int"
10         resultType="com.tarena.entity.Module">
11         select * from module_info where module_id in (
12             select rm.module_id
13             from admin_role ar
14             inner join role_info ri on ri.role_id=ar.role_id
15             inner join role_module rm on rm.role_id=ri.role_id
16             where ar.admin_id=#{adminId}
17         ) order by module_id
18     </select>
19
20 </mapper>


Step6.5、验证码生成的方法





1 package com.tarena.util;
2
3 import java.awt.Color;
4 import java.awt.Font;
5 import java.awt.Graphics;
6 import java.awt.image.BufferedImage;
7 import java.io.ByteArrayInputStream;
8 import java.io.ByteArrayOutputStream;
9 import java.io.IOException;
10 import java.io.InputStream;
11 import java.util.HashMap;
12 import java.util.Map;
13 import java.util.Random;
14
15 import com.sun.image.codec.jpeg.JPEGCodec;
16 import com.sun.image.codec.jpeg.JPEGImageEncoder;
17
18 public final class ImageUtil {
19
20     private static final char[] chars = { '0', '1', '2', '3', '4', '5', '6',
21             '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I' };
22     private static final int SIZE = 4;
23     private static final int LINES = 5;
24     private static final int WIDTH = 80;
25     private static final int HEIGHT = 40;
26     private static final int FONT_SIZE = 30;
27
28     public static Map<String, BufferedImage> createImage() {
29         StringBuffer sb = new StringBuffer();
30         BufferedImage image = new BufferedImage(WIDTH, HEIGHT,
31                 BufferedImage.TYPE_INT_RGB);
32         Graphics graphic = image.getGraphics();
33         graphic.setColor(Color.LIGHT_GRAY);
34         graphic.fillRect(0, 0, WIDTH, HEIGHT);
35         Random ran = new Random();
36         // 画随机字符
37         for (int i = 1; i <= SIZE; i++) {
38             int r = ran.nextInt(chars.length);
39             graphic.setColor(getRandomColor());
40             graphic.setFont(new Font(null, Font.BOLD + Font.ITALIC, FONT_SIZE));
41             graphic.drawString(chars[r] + "", (i - 1) * WIDTH / SIZE,
42                     HEIGHT / 2);
43             sb.append(chars[r]);// 将字符保存,存入Session
44         }
45         // 画干扰线
46         for (int i = 1; i <= LINES; i++) {
47             graphic.setColor(getRandomColor());
48             graphic.drawLine(ran.nextInt(WIDTH), ran.nextInt(HEIGHT),
49                     ran.nextInt(WIDTH), ran.nextInt(HEIGHT));
50         }
51         Map<String, BufferedImage> map = new HashMap<String, BufferedImage>();
52         map.put(sb.toString(), image);
53         return map;
54     }
55
56     public static Color getRandomColor() {
57         Random ran = new Random();
58         Color color = new Color(ran.nextInt(256), ran.nextInt(256),
59                 ran.nextInt(256));
60         return color;
61     }
62
63     public static InputStream getInputStream(BufferedImage image)
64             throws IOException {
65         ByteArrayOutputStream bos = new ByteArrayOutputStream();
66         JPEGImageEncoder encoder = JPEGCodec.createJPEGEncoder(bos);
67         encoder.encode(image);
68         byte[] imageBts = bos.toByteArray();
69         InputStream in = new ByteArrayInputStream(imageBts);
70         return in;
71     }
72
73 }


验证码生成的方法
 

 Step7、在控制层编写用户登入的逻辑

1 package com.tarena.controller;
2
3 import java.awt.image.BufferedImage;
4 import java.io.OutputStream;
5 import java.util.HashMap;
6 import java.util.List;
7 import java.util.Map;
8 import javax.annotation.Resource;
9 import javax.imageio.ImageIO;
10 import javax.servlet.http.HttpServletResponse;
11 import javax.servlet.http.HttpSession;
12 import org.springframework.stereotype.Controller;
13 import org.springframework.web.bind.annotation.RequestMapping;
14 import org.springframework.web.bind.annotation.ResponseBody;
15 import com.tarena.dao.AdminDao;
16 import com.tarena.entity.Admin;
17 import com.tarena.entity.Module;
18 import com.tarena.util.ImageUtil;
19
20 @Controller
21 @RequestMapping("/login")
22 public class LoginController extends BaseController {
23
24     /*
25      * 设置四种状态,对应不同的错误
26      */
27     private final static int SUCCESS = 0;
28
29     private final static int ADMIN_CODE_ERROR = 1;
30
31     private final static int PASSWORD_ERROR = 2;
32
33     private final static int IMAGE_CODE_ERROR = 3;
34
35     @Resource
36     private AdminDao adminDao;
37
38     @RequestMapping("/toLogin.do")
39     public String toLogin() {
40         return "main/login";
41     }
42
43     @RequestMapping("/toIndex.do")
44     public String toIndex() {
45         return "main/index";
46     }
47
48     @RequestMapping("/nopower.do")
49     public String nopower() {
50         return "main/nopower";
51     }
52
53     @RequestMapping("/login.do")
54     @ResponseBody
55     public Map<String, Object> login(
56             String adminCode,
57             String password,
58             String code,
59             HttpSession session) {
60         Map<String, Object> result = new HashMap<String, Object>();
61
62         String imageCode = (String) session.getAttribute("imageCode");
63         if(code == null
64                 || !code.equalsIgnoreCase(imageCode)) {
65             result.put("flag", IMAGE_CODE_ERROR);
66             return result;
67         }
68
69         Admin admin = adminDao.findByCode(adminCode);
70         if(admin == null) {
71             result.put("flag", ADMIN_CODE_ERROR);
72             return result;
73         } else if (!admin.getPassword().equals(password)) {
74             result.put("flag", PASSWORD_ERROR);
75             return result;
76         } else {
77             //发送登录成功的admin号到session
78             session.setAttribute("admin", admin);
79             //获得登录这个admin号的权限范围
80             List<Module> modules =
81                 adminDao.findModulesByAdmin(admin.getAdmin_id());
82             session.setAttribute("allModules", modules);
83             result.put("flag", SUCCESS);
84             return result;
85         }
86     }
87
88     //验证码生成
89     @RequestMapping("/createImage.do")
90     public void createImage(
91             HttpServletResponse response, HttpSession session)
92             throws Exception {
93         Map<String, BufferedImage> imageMap = ImageUtil.createImage();
94         String code = imageMap.keySet().iterator().next();
95         session.setAttribute("imageCode", code);
96
97         BufferedImage image = imageMap.get(code);
98
99         response.setContentType("image/jpeg");
100         OutputStream ops = response.getOutputStream();
101         ImageIO.write(image, "jpeg", ops);
102         ops.close();
103     }
104
105 }


 Step8、用户在登录页面和登录后进入的主页及提示用户没有权限的页面

login.jsp:↓

1 <%@page pageEncoding="utf-8"%>
2 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
3 <html xmlns="http://www.w3.org/1999/xhtml">
4     <head>
5         <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
6         <title>达内-NetCTOSS</title>
7         <link type="text/css" rel="stylesheet" media="all" href="../styles/global.css" />
8         <link type="text/css" rel="stylesheet" media="all" href="../styles/global_color.css" />
9         <script type="text/javascript" language="javascript" src="../js/jquery-1.11.1.js"></script>
10         <script type="text/javascript" language="javascript">
11             //登录校验
12             function check_login() {
13                 var admin_code = $("#admin_code").val();
14                 if(admin_code == "") {
15                     $("#admin_code_msg").text("请输入账号.");
16                     return;
17                 }
18
19                 var password = $("#password").val();
20                 if(password == "") {
21                     $("#password_msg").text("请输入密码.");
22                     return;
23                 }
24
25                 var code = $("#code").val();
26                 if(code == "") {
27                     $("#code_msg").text("请输入验证码.");
28                     return;
29                 }
30
31                 $.post(
32                     "login.do",
33                     $("#myform").serialize(),
34                     function(data) {
35                         if(data.flag==1) {
36                             //账号错误
37                             $("#admin_code_msg").text("账号错误.");
38                         } else if(data.flag==2) {
39                             //密码错误
40                             $("#password_msg").text("密码错误.");
41                         } else if(data.flag==3) {
42                             //验证码错误
43                             $("#code_msg").text("验证码错误.");
44                             change();
45                         } else {
46                             //成功
47                             location.href = "toIndex.do";
48                         }
49                     }
50                 );
51             }
52             //设置提示信息
53             function set_msg(id, msg) {
54                 $("#"+id).text(msg);
55             }
56             //刷新验证码
57             function change() {
58                 $("#code_image").attr("src", "createImage.do?date=" + new Date().getTime());
59             }
60         </script>
61     </head>
62     <body class="index">
63         <div class="login_box">
64             <form action="login.do" method="post" >
65                 <table>
66                     <tr>
67                         <td class="login_info">账号:</td>
68                         <td colspan="2">
69                             <input type="text" name="adminCode"  class="width150" onfocus="set_msg('admin_code_msg','30长度的字母、数字和下划线');"/>
70                         </td>
71                         <td class="login_error_info"><span class="required" >30长度的字母、数字和下划线</span></td>
72                     </tr>
73                     <tr>
74                         <td class="login_info">密码:</td>
75                         <td colspan="2">
76                             <input type="password" name="password"  class="width150" onfocus="set_msg('password_msg','30长度的字母、数字和下划线');"/>
77                         </td>
78                         <td><span class="required" >30长度的字母、数字和下划线</span></td>
79                     </tr>
80                     <tr>
81                         <td class="login_info">验证码:</td>
82                         <td class="width70"><input name="code" type="text" class="width70"  onfocus="set_msg('code_msg','');"/></td>
83                         <td><img src="createImage.do" alt="验证码" title="点击更换"  onclick="change();"/></td>
84                         <td><span class="required" ></span></td>
85                     </tr>
86                     <tr>
87                         <td></td>
88                         <td class="login_button" colspan="2">
89                             <a href="javascript:check_login();"><img src="../images/login_btn.png" /></a>
90                         </td>
91                         <td><span class="required"></span></td>
92                     </tr>
93                 </table>
94             </form>
95         </div>
96     </body>
97 </html>


menu.jsp ↓

1 <%@page pageEncoding="utf-8"%>
2 <%@taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
3 <ul >
4     <c:choose>
5         <c:when test="${currentModule==0 }">
6             <li><a href="${pageContext.request.contextPath }/login/toIndex.do" class="index_on"></a></li>
7         </c:when>
8         <c:otherwise>
9             <li><a href="${pageContext.request.contextPath }/login/toIndex.do" class="index_off"></a></li>
10         </c:otherwise>
11     </c:choose>
12
13     <c:forEach items="${allModules }" var="module">
14         <c:if test="${module.module_id==1 }">
15             <c:choose>
16                 <c:when test="${currentModule==1 }">
17                     <li><a href="${pageContext.request.contextPath }/role/findRole.do?currentPage=1" class="role_on"></a></li>
18                 </c:when>
19                 <c:otherwise>
20                     <li><a href="${pageContext.request.contextPath }/role/findRole.do?currentPage=1" class="role_off"></a></li>
21                 </c:otherwise>
22             </c:choose>
23         </c:if>
24         <c:if test="${module.module_id==2 }">
25             <c:choose>
26                 <c:when test="${currentModule==2 }">
27                     <li><a href="${pageContext.request.contextPath }/admin/findAdmin.do?currentPage=1" class="admin_on"></a></li>
28                 </c:when>
29                 <c:otherwise>
30                     <li><a href="${pageContext.request.contextPath }/admin/findAdmin.do?currentPage=1" class="admin_off"></a></li>
31                 </c:otherwise>
32             </c:choose>
33         </c:if>
34         <c:if test="${module.module_id==3 }">
35             <c:choose>
36                 <c:when test="${currentModule==3 }">
37                     <li><a href="${pageContext.request.contextPath }/cost/findCost.do?currentPage=1" class="fee_on"></a></li>
38                 </c:when>
39                 <c:otherwise>
40                     <li><a href="${pageContext.request.contextPath }/cost/findCost.do?currentPage=1" class="fee_off"></a></li>
41                 </c:otherwise>
42             </c:choose>
43         </c:if>
44         <c:if test="${module.module_id==4 }">
45             <c:choose>
46                 <c:when test="${currentModule==4 }">
47                     <li><a href="${pageContext.request.contextPath }/account/findAccount.do?currentPage=1" class="account_on"></a></li>
48                 </c:when>
49                 <c:otherwise>
50                     <li><a href="${pageContext.request.contextPath }/account/findAccount.do?currentPage=1" class="account_off"></a></li>
51                 </c:otherwise>
52             </c:choose>
53         </c:if>
54         <c:if test="${module.module_id==5 }">
55             <c:choose>
56                 <c:when test="${currentModule==5 }">
57                     <li><a href="${pageContext.request.contextPath }/service/findService.do?currentPage=1" class="service_on"></a></li>
58                 </c:when>
59                 <c:otherwise>
60                     <li><a href="${pageContext.request.contextPath }/service/findService.do?currentPage=1" class="service_off"></a></li>
61                 </c:otherwise>
62             </c:choose>
63         </c:if>
64     </c:forEach>
65     <li><a href="user/user_info.html" class="information_off"></a></li>
66     <li><a href="user/user_modi_pwd.html" class="password_off"></a></li>
67 </ul>


 nopower.jsp





<%@page pageEncoding="utf-8"%>
<%@taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
<%
String path = request.getContextPath();
String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
%>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>达内-NetCTOSS</title>
<link type="text/css" rel="stylesheet" media="all" href="../styles/global.css" />
<link type="text/css" rel="stylesheet" media="all" href="../styles/global_color.css" />
<script language="javascript" type="text/javascript">
var timer;
//启动跳转的定时器
function startTimes() {
timer = window.setInterval(showSecondes,1000);
}

var i = 5;
function showSecondes() {
if (i > 0) {
i--;
document.getElementById("secondes").innerHTML = i;
}
else {
window.clearInterval(timer);
location.href = "<%=path%>/login/toIndex.do";
}
}

//取消跳转
function resetTimer() {
if (timer != null && timer != undefined) {
window.clearInterval(timer);
//location.href = "index.html";
window.history.back();
}
}
</script>
</head>
<body class="error_power_page" onload="startTimes();">
<h1 >
您无权访问此页面, <span >5</span> 秒后将自动跳转,立即跳转请点击 
<a class="index.html" href="javascript:resetTimer();">返回</a>
</h1>
</body>
</html>


没有权限的提示页面
 

 Step9、写3个拦截器

CheckModuleInterceptor:↓





1 package com.tarena.interceptor;
2
3 import java.util.List;
4
5 import javax.servlet.http.HttpServletRequest;
6 import javax.servlet.http.HttpServletResponse;
7
8 import org.springframework.web.servlet.HandlerInterceptor;
9 import org.springframework.web.servlet.ModelAndView;
10
11 import com.tarena.entity.Module;
12
13 public class CheckModuleInterceptor implements HandlerInterceptor {
14
15     @Override
16     public void afterCompletion(HttpServletRequest arg0,
17             HttpServletResponse arg1, Object arg2, Exception arg3)
18             throws Exception {
19
20     }
21
22     @Override
23     public void postHandle(HttpServletRequest arg0, HttpServletResponse arg1,
24             Object arg2, ModelAndView arg3) throws Exception {
25
26     }
27
28     @SuppressWarnings("unchecked")
29     @Override
30     public boolean preHandle(HttpServletRequest request,
31             HttpServletResponse response, Object obj) throws Exception {
32         //获取登录用户有权限的所有模块
33         List<Module> modules = (List<Module>)
34                 request.getSession().getAttribute("allModules");
35         //获取用户当前要访问的模块
36         int currentModule = (Integer)
37                 request.getSession().getAttribute("currentModule");
38         //判断用户有权限的模块是否包含当前模块
39         for (Module module : modules) {
40             if (module.getModule_id() == currentModule) {
41                 //有当前访问模块的权限
42                 return true;
43             }
44         }
45         //没有当前访问模块的权限
46         response.sendRedirect(
47                 request.getContextPath() + "/login/nopower.do");
48         return false;
49     }
50
51 }


View Code
CurrentModuleInterceptor:↓





1 package com.tarena.interceptor;
2
3 import javax.servlet.http.HttpServletRequest;
4 import javax.servlet.http.HttpServletResponse;
5 import org.springframework.web.servlet.HandlerInterceptor;
6 import org.springframework.web.servlet.ModelAndView;
7
8 public class CurrentModuleInterceptor implements HandlerInterceptor {
9
10     @Override
11     public void afterCompletion(HttpServletRequest arg0,
12             HttpServletResponse arg1, Object arg2, Exception arg3)
13             throws Exception {
14
15     }
16
17     @Override
18     public void postHandle(HttpServletRequest arg0, HttpServletResponse arg1,
19             Object arg2, ModelAndView arg3) throws Exception {
20
21     }
22
23     @Override
24     public boolean preHandle(HttpServletRequest request,
25             HttpServletResponse response, Object obj) throws Exception {
26         // 判断当前用户访问的模块
27         String url = request.getRequestURL().toString();
28         int currentModule = 0; // 默认0是NETCTOSS首页
29         if (url.contains("role")) {
30             currentModule = 1;
31         } else if (url.contains("admin")) {
32             currentModule = 2;
33         } else if (url.contains("cost")) {
34             currentModule = 3;
35         } else if (url.contains("account")) {
36             currentModule = 4;
37         } else if (url.contains("service")) {
38             currentModule = 5;
39         }
40
41         request.getSession().setAttribute(
42                 "currentModule", currentModule);
43
44         return true;
45     }
46
47 }


View Code
LoginInterceptor:↓





1 package com.tarena.interceptor;
2
3 import javax.servlet.http.HttpServletRequest;
4 import javax.servlet.http.HttpServletResponse;
5
6 import org.springframework.web.servlet.HandlerInterceptor;
7 import org.springframework.web.servlet.ModelAndView;
8
9 import com.tarena.entity.Admin;
10
11 public class LoginInterceptor implements HandlerInterceptor {
12
13     @Override
14     public void afterCompletion(HttpServletRequest arg0,
15             HttpServletResponse arg1, Object arg2, Exception arg3)
16             throws Exception {
17
18     }
19
20     @Override
21     public void postHandle(HttpServletRequest arg0, HttpServletResponse arg1,
22             Object arg2, ModelAndView arg3) throws Exception {
23
24     }
25
26     @Override
27     public boolean preHandle(HttpServletRequest request,
28             HttpServletResponse response, Object obj) throws Exception {
29         Admin admin = (Admin) request.getSession().getAttribute("admin");
30         if(admin == null) {
31             response.sendRedirect(
32                 request.getContextPath() + "/login/toLogin.do");
33             return false;
34         } else {
35             return true;
36         }
37     }
38
39 }


View Code
 

 

 业务实现逻辑:

step1 用户登录

首先当用户访问toLogin.do时,

@RequestMapping("/toLogin.do")
public String toLogin() {
return "main/login";
}


这时用户在login.jsp生成的页面中填写账号密码和验证码,填写完毕后提交。

<form action="login.do" method="post" >


这时将跳转至login.do页面,就会运行控制器LoginController里的login()方法

@RequestMapping("/login.do")
@ResponseBody
public Map<String, Object> login(
String adminCode,
String password,
String code,
HttpSession session) {
Map<String, Object> result = new HashMap<String, Object>();

String imageCode = (String) session.getAttribute("imageCode");
if(code == null
|| !code.equalsIgnoreCase(imageCode)) {
result.put("flag", IMAGE_CODE_ERROR);
return result;
}

Admin admin = adminDao.findByCode(adminCode);
if(admin == null) {
result.put("flag", ADMIN_CODE_ERROR);
return result;
} else if (!admin.getPassword().equals(password)) {
result.put("flag", PASSWORD_ERROR);
return result;
} else {
//发送登录成功的admin号到session
session.setAttribute("admin", admin);
//获得登录这个admin号的权限范围
List<Module> modules =
adminDao.findModulesByAdmin(admin.getAdmin_id());
session.setAttribute("allModules", modules);
result.put("flag", SUCCESS);
return result;
}
}


如果账号和密码验证码有错误,将根据不同的错误生成不同的result结果,将在网页上显示。

在3个数据填写正确之后,页面跳转至toIndex.do,并且发送2个对象"admin"(用户名称)和" modules "(用户的权限编号)保存到session,

这里的modules是通过用admin的值调用findModulesByAdmin()方法获得的。

 

step2--modules的权限编号的获得

   AdminDao接口里的  List<Module> findModulesByAdmin(int adminId) 方法;

  实现在 AdminMapper.xml的映射里的SQL语句

<select
parameterType="int"
resultType="com.tarena.entity.Module">
select * from module_info(模块表) where module_id in (
select rm.module_id
from admin_role ar
inner join role_info(角色表) ri on ri.role_id=ar.role_id
inner join role_module(角色模块表) rm on rm.role_id=ri.role_id
where ar.admin_id=#{adminId}
) order by module_id
</select>


  这里是个链表,role_info ri关联ri.role_id,通过ar.role_id

          role_module rm 关联 rm.role_id,通过ri.role_id

1、 登录的id是 admin_info管理员表,根据登录的admin_id获得admin_role表中的role_id,

再通过role_module中的role_id找到 role_module的module_id,再根据module_id获得后面的字符串,即可以直到登录的这个号有哪些权限

相当于,先获取是什么角色,再从是什么角色获取有什么权限

2、其数据库管理的逻辑是,每个账号使用者,可以用不同的角色(类似职位),而每个不同角色有不同的权限,从上而下则是首先可以增删改查角色,

然后再对每个角色所拥有的权限进行增删改查。

 

这里已经获取了登录账号所拥有的权限,回过头看login方法,在运行SQL语句之后将查询到的权限的所对应的int值全部放入到modules集合中。

List<Module> modules =
adminDao.findModulesByAdmin(admin.getAdmin_id());


 

 

step3 拦截器

     在applicationContext.xml中配置3个拦截器,第1个LoginInterceptor在除了toLogin.do,Login.do,createImage.do(验证码)这3个页面不拦截外,

对所有页面进行拦截。第2个和第3个拦截器CurrentModuleInterceptor和CheckModuleInterceptor对所有页面进行拦截,断绝一切可能从其他地址

访问到所不拥有的权限能看到的模块。

  

<!-- 注册拦截器 -->
<mvc:interceptors>
<!-- 登录检查拦截器 -->
<mvc:interceptor>
<mvc:mapping path="/**"/>
<mvc:exclude-mapping path="/login/toLogin.do"/>
<mvc:exclude-mapping path="/login/login.do"/>
<mvc:exclude-mapping path="/login/createImage.do"/>
<bean class="com.tarena.interceptor.LoginInterceptor"/>
</mvc:interceptor>
<!-- 判断当前模块拦截器 -->
<mvc:interceptor>
<mvc:mapping path="/**"/>
<bean class="com.tarena.interceptor.CurrentModuleInterceptor"/>
</mvc:interceptor>
<!-- 权限检查拦截器 -->
<mvc:interceptor>
<mvc:mapping path="/**"/>
<mvc:exclude-mapping path="/login/*"/>
<bean class="com.tarena.interceptor.CheckModuleInterceptor"/>
</mvc:interceptor>
</mvc:interceptors>


 

 

CurrentModuleInterceptor:

首先在CurrentModuleInterceptor拦截器中,将用户访问的链接转换为字符串,如果有包含role,admin,cost,account,service字符串,则按照其功能转换为对应的int值,并且返还给curentModule对象,命名为"currentModule"

并发送出去。

@Override
public boolean preHandle(HttpServletRequest request,
HttpServletResponse response, Object obj) throws Exception {
// 判断当前用户访问的模块
String url = request.getRequestURL().toString();
int currentModule = 0; // 默认0是NETCTOSS首页
if (url.contains("role")) {
currentModule = 1;
} else if (url.contains("admin")) {
currentModule = 2;
} else if (url.contains("cost")) {
currentModule = 3;
} else if (url.contains("account")) {
currentModule = 4;
} else if (url.contains("service")) {
currentModule = 5;
}

request.getSession().setAttribute(
"currentModule", currentModule);

return true;
}


 

CheckModuleInterceptor

 首先获取之前传入的allModules,即用户所拥有的权限对象,然后再获取用户之前访问链接而产生的对应的curentModule对象,强转为int型,因为权限编号为int,再通过foreach循环判断两者是否相等,即可以判断用户是否有权限进行访问。如果有权限则返回true,没有权限则跳转至"/login/nopower.do",即提示用户没有权限的页面,并且返回false

@SuppressWarnings("unchecked")
@Override
public boolean preHandle(HttpServletRequest request,
HttpServletResponse response, Object obj) throws Exception {
//获取登录用户有权限的所有模块
List<Module> modules = (List<Module>)
request.getSession().getAttribute("allModules");
//获取用户当前要访问的模块
int currentModule = (Integer)
request.getSession().getAttribute("currentModule");
//判断用户有权限的模块是否包含当前模块
for (Module module : modules) {
if (module.getModule_id() == currentModule) {
//有当前访问模块的权限
return true;
}
}
//没有当前访问模块的权限
response.sendRedirect(
request.getContextPath() + "/login/nopower.do");
return false;
}


 

step4

 用户填写完账号密码验证码之后跳转至toIndex.do之后,程序访问index页面,

@RequestMapping("/toIndex.do")
public String toIndex() {
return "main/index";
}


 

而index页面导入了menu.jsp页面,接着程序走menu.jsp

<jsp:include page="/WEB-INF/main/menu.jsp" />


在menu.jsp中,使用循环查找之前传入的module对象中的值,有哪个数值就显示数值对应的页面,这样就做到了,只显示用户所拥有权限的对应页面(有多个就显示多个),没有的就不会显示出来。

<c:forEach items="${allModules }" var="module">
<c:if test="${module.module_id==1 }">
<c:choose>
<c:when test="${currentModule==1 }">
<li><a href="${pageContext.request.contextPath }/role/findRole.do?currentPage=1" class="role_on"></a></li>
</c:when>
<c:otherwise>
<li><a href="${pageContext.request.contextPath }/role/findRole.do?currentPage=1" class="role_off"></a></li>
</c:otherwise>
</c:choose>
</c:if>


在数据库中录入的每个模块对应的int值

insert into MODULE_INFO
values
(1,'角色管理');
insert into MODULE_INFO
values
(2,'管理员');
insert into MODULE_INFO
values
(3,'资费管理');
insert into MODULE_INFO
values
(4,'账务账号');
insert into MODULE_INFO
values
(5,'业务账号');
insert into MODULE_INFO
values
(6,'账单管理');
insert into MODULE_INFO values(7,'报表');

 

最后这里表示个人信息和修改密码两项无论是什么权限都会显示。

<li><a href="user/user_info.html" class="information_off"></a></li>
<li><a href="user/user_modi_pwd.html" class="password_off"></a></li>


 

 

以及通过使用

<c:choose>
<c:when test="${currentModule==0 }">
<li><a href="${pageContext.request.contextPath }/login/toIndex.do" class="index_on"></a></li>
</c:when>
<c:otherwise>
<li><a href="${pageContext.request.contextPath }/login/toIndex.do" class="index_off"></a></li>
</c:otherwise>
</c:choose>


因为之前在拦截器中将currentModule的值设置默认为0

public boolean preHandle(HttpServletRequest request,
HttpServletResponse response, Object obj) throws Exception {
// 判断当前用户访问的模块
String url = request.getRequestURL().toString();
int currentModule = 0; // 默认0是NETCTOSS首页


添加一个点击返回首页的链接。

这样每个能显示的按钮,绑定一个链接跳转相应的页面,就实现了用户的权限管理。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: