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

news/2024/5/14 17:29:29/文章来源:https://blog.csdn.net/lx520aa/article/details/77840449

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

 需求:

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

例如,一个使用者拥有“资费管理”权限,表示该使 用者可以操作“资费管理”模块,以执行资费管理的操作。权限由 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" οnfοcus="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" οnfοcus="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"  οnfοcus="set_msg('code_msg','');"/></td>
83                         <td><img src="createImage.do" alt="验证码" title="点击更换"  οnclick="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" οnlοad="startTimes();">
<h1 >
您无权访问此页面,&nbsp;<span >5</span>&nbsp;秒后将自动跳转,立即跳转请点击&nbsp;
<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个拦截器CurrentModuleInterceptorCheckModuleInterceptor对所有页面进行拦截,断绝一切可能从其他地址

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

  

<!-- 注册拦截器 -->
<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首页

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

这样每个能显示的按钮,绑定一个链接跳转相应的页面,就实现了用户的权限管理。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.luyixian.cn/news_show_853370.aspx

如若内容造成侵权/违法违规/事实不符,请联系dt猫网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

webmagic爬取渲染网站

最近突然得知之后的工作有很多数据采集的任务&#xff0c;有朋友推荐webmagic这个项目&#xff0c;就上手玩了下。发现这个爬虫项目还是挺好用&#xff0c;爬取静态网站几乎不用自己写什么代码&#xff08;当然是小型爬虫了~~|&#xff09;。好了&#xff0c;废话少说&#xff…

Roslyn导致发布网站时报错-编译失败

最近新升级了Visual Studio 2017&#xff0c;创建的Web项目Bin目录中多了一个叫roslyn的文件夹&#xff0c;该文件夹导致网站在某些服务器上发布出错 从网上搜索了一下&#xff0c;Roslyn是新出的动态编译工具 但是在服务器上安装.net4.6后仍然提示编译出错。 解决方法&#x…

搜索引擎优化(SEO)新手指南(超实用)

from&#xff1a;http://www.kenengba.com/post/556.html这个指南不会告诉你如何能在Google排第一位&#xff0c;但能使你的网站或博客对浏览者和搜索引擎更友好。 一、使用独特的、准确的标题 不管对于浏览者还是搜索引擎来说&#xff0c;标题对于一个网站是非常重要的。而标题…

浏览英文网站必会的100个词汇

许多人刚开始接触纯英文网站的时候&#xff0c;看到满版的英文&#xff0c;不免有些望而却步&#xff0c;其实浏览英文网站并没有想象中的那么难&#xff0c;只要你掌握了基本的一些词汇&#xff0c;很快就会寻得一些浏览规律&#xff0c;今天要给大家介绍一些在浏览是使用英文…

常用的开源社区网站和面试刷题网站

1、GitHub&#xff08;https://github.com/&#xff09; 全球最大开源社区。 2、码云&#xff08;https://gitee.com/&#xff09; 可以看做GitHub的国内版。 3、LeetCode&#xff08;https://leetcode-cn.com/&#xff09; 经典的刷题网站&#xff0c;主要是算法题。 4、LintC…

自建CA给内部网站颁发SSL证书

Windows Server - 建设篇 第二章 自建CA给内部网站颁发SSL证书Windows Server - 建设篇系列文章回顾下章内容前言实施步骤Openssl申请证书签发请求&#xff08;带SAN扩展属性&#xff09;参考来源系列文章回顾 第一章 Windows Server 2016搭建企业CA证书服务 下章内容 第三章…

Saleor:开源、免费的无头电子商务平台——系列教程,快速打造属于你的电商网站

Saleor&#xff1a;开源、免费的无头&#xff08;Headless eCommerce&#xff09;电子商务平台 项目&#xff1a;saleor stars&#xff1a;6.7k 简介&#xff1a;开源的无头&#xff08;Headless eCommerce&#xff09;电子商务平台&#xff08;商城&网店&#xff09; 官网…

React项目全球新闻发布管理系统 - 新版问题解决方式整理及部署网站至 Netlify

整理了一下新版的变化以及遇到的坑的解决办法&#xff0c;最后也会分享将网站及接口部署的方式。 千锋前端-React全家桶_React项目全球新闻发布管理系统 https://www.bilibili.com/video/BV1fw411d7R5 文章目录P4P5P6P11P15P17P18P22P29P30P34P38P41P43P45P50P67进阶: 多语系网…

网站图片都有规格、质量大小限制,如何处理图片的规格、大小呢?

对于网站运营图片都有相应的尺寸规格限制&#xff0c;比如常见的如下图&#xff1a; 1、大背景&#xff1a;尺寸不限&#xff0c;但图案最好不要太大太复杂 2、页眉背景&#xff1a;尺寸为770*40px&#xff08;px为像素单位&#xff09;&#xff0c;图案自己选 3、标题背景&…

老馒头修图网的故事,网站经营的心路历程

也许你是第一次听说老馒头修图网&#xff0c;它并不是什么神奇的网站&#xff0c;只是一个普通的图片处理网站&#xff0c;可以帮助网友在线快速修剪图片、压缩图片等。从图片处理的资历来讲&#xff0c;老馒头修图网是个不折不扣的新人&#xff0c;没有强大的背景&#xff0c;…

公司文员上传团建图片到网站的坎坷小道

作为一个公司文员&#xff0c;大部分时间都在处理公司接待、收发快递、协助行政杂务&#xff0c;没怎么接触过系统也不太懂得网站后台操作。公司团建回来&#xff0c;我又多了份新活&#xff0c;那就是将团建图片上传到公司官网&#xff0c;本来觉得不是什么难的事情&#xff0…

王者网站想以php结尾,玩王者荣耀,我用PHP分析了选英雄的那些事儿……

原标题&#xff1a;玩王者荣耀&#xff0c;我用PHP分析了选英雄的那些事儿……选英雄的那些事儿&#xff0c;你可能会想到到什么.....这里所介绍的是王者荣耀里关于英雄的各种“最”&#xff0c;这里分析的都是英雄自身属性及资料&#xff0c;不涉及玩家操作的成分。作 为目前最…

如何在局域网服务器部署网站,局域网如何对服务器配置

在局域网中&#xff0c;我们如何对服务器进行配置呢?学习啦小编为大家整理了相关内容&#xff0c;供大家参考阅读!局域网内对服务器进行配置的方法首先打开电脑的控制面板&#xff0c;点击控制面板中的卸载程序。2这时候进入了程序与功能对话框&#xff0c;点击右边栏中的启用…

大型门户网站架构服务部署研究说明

笔者经常被朋友问起&#xff0c;该如何设计一个大型的门户网站架构。目前中小型网站&#xff0c;由于数据量相对来说比较少&#xff0c;特别是普通的企业网站&#xff0c;几乎没有什么人访问&#xff0c;因此&#xff0c;大部分都是单机版的服务架构&#xff0c;即&#xff1a;…

搭建网站运行环境

云上部署WordPress网站 步骤&#xff1a; 安装与服务器ECS安装和配置开发环境&#xff1a;Web服务器、数据库等部署WordPress网站&#xff1a;下载安装包、安装和配置WordPress 1&#xff09; 安装与服务器ECS 略 2&#xff09;安装和配置开发环境&#xff1a;Web服务器、数…

【服务器架构】大型网站结构介绍

大型网站架构介绍 特点&#xff1a;高并发、大流量、高可用、海量数据。 目录 大型网站架构介绍 1、初始阶段的网络架构 2、应用服务和数据服务分离 3、使用缓存改善网站性能 4、使用应用服务器集群改善网站的并发处理能力 5、数据库读写分离 6、使用反向代理和CDN加上…

Webbench网站压测工具

Webbench是一个在Linux下使用的非常简单的网站压测工具。他本身是一个单进程&#xff0c;使用fork()模拟多个客户端同时访问我们设定的url&#xff0c;用来测试网站在压力下的性能。最多可以模拟3万个并发连接去测试网站的负载能力。Webbench使用C语言编写&#xff0c;源码只有…

网站建设之HTML中用表格实现课程表

效果图&#xff1a; 代码&#xff1a; <html> <title>课程表</title> <head> </head> <body> <font size5><center>课程表</center></font> <table align"center" border"1px" bordercol…

网站建设之HTML中用表单和表格嵌套实现会员注册表

效果图&#xff1a; 代码&#xff1a; <html> <head> <title>注册页面</title> </head> <body> <form name"register" action"url" method"get"> <table border"2" align"center&…

网站建设之CSS中用类选择器实现登录表单

效果图&#xff1a; 代码&#xff1a; <html> <head> <title>登录页面</title> <style type"text/css"> .box1{border:solid 2px purple;} .box2{border:solid 2px red;} </style> </head> <body> <form name&q…