crm之权限整理1

权限的整理

 (1)粗粒度权限 用户登录的时候 把用户名记录下来放入到session中 如果你在地址栏中非法输入 而你有没有登录 就会自动跳入到登录界面 这个功能的实现

举例子 :

他的路径是: http://localhost:8080/MyCRM/

 当请求这个路径的时候 一般会默认的走 MYCRM下面的index路径 

但是为了安全 还是跳转到web-inf下面的login 因为web-inf下面的文件 不可以在地址栏直接输入 所以相对来说还算安全..

<%@ page language="java" pageEncoding="UTF-8" contentType="text/html; charset=utf-8"%>
<jsp:forward page="/WEB-INF/page/login.jsp"></jsp:forward>


在login.jsp中 开始处理这一系列的操作  比如说表单中用户名和密码的验证 还有 验证码的实现 还有cookie的实现

第一 js前台验证

(用户名和密码不能为空验证:)

function checkSubmit(){
if($("#name").val().length<=0){
alert("登陆的用户名不能为空");
return false;
}
if($("#password").val().length<=0){
alert("登陆的密码不能为空");
return false;
}
/*if($("#checkNum").val().length<=0){
alert("验证码不能为空");
return false;
}*/
document.forms[0].submit();
}


(2)点击验证码改变的js

function changeCheckNum(){
var checkNumImage_=document.getElementById("checkNumImage");
checkNumImage_.src="${pageContext.request.contextPath}/image.jsp?timeStamp="+new Date().getTime();
}


(3)cookie的整理


 验证码的产生:一般写在一个image.jsp中

<%@ page language="java" pageEncoding="UTF-8" %>
<%@ page contentType="image/jpeg" import="java.awt.*,java.awt.image.*,java.util.*,javax.imageio.*" %>
<%!
Color getRandColor(int fc, int bc) {//给定范围获得随机颜色
Random random = new Random();
if (fc > 255)
fc = 255;
if (bc > 255)
bc = 255;
int r = fc + random.nextInt(bc - fc);
int g = fc + random.nextInt(bc - fc);
int b = fc + random.nextInt(bc - fc);
return new Color(r, g, b);
}%>

<%
//设置页面不缓存
response.setHeader("Pragma", "No-cache");
response.setHeader("Cache-Control", "no-cache");
response.setDateHeader("Expires", 0);

//生成随机验证码
Random random = new Random();
String sRand = "";
for (int i = 0; i < 4; i++) {
String rand = String.valueOf(random.nextInt(10));
sRand += rand;
}
// 将认证码存入SESSION
session.setAttribute("CHECK_NUMBER_KEY", sRand);

// 在内存中创建图象
int width = 55;
int height = 20;
BufferedImage image = new BufferedImage(width, height,
BufferedImage.TYPE_INT_RGB);

// 获取图形上下文
Graphics g = image.getGraphics();

// 设定背景色
g.setColor(getRandColor(200, 250));
g.fillRect(0, 0, width, height);

//设定字体
g.setFont(new Font("serif", Font.CENTER_BASELINE, 16));

//画边框
//g.setColor(new Color(1));
//g.drawRect(0,0,width-1,height-1);

// 随机产生155条干扰线,使图象中的认证码不易被其它程序探测到
g.setColor(getRandColor(160, 200));
for (int i = 0; i < 100; i++) {
int x = random.nextInt(width);
int y = random.nextInt(height);
int xl = random.nextInt(12);
int yl = random.nextInt(12);
g.drawLine(x, y, x + xl, y + yl);
}

for (int i = 0; i < 4; i++) {
String rand = sRand.substring(i, i + 1);
// 将认证码显示到图象中
g.setColor(new Color(20 + random.nextInt(110), 20 + random
.nextInt(110), 20 + random.nextInt(110)));
//调用函数出来的颜色相同,可能是因为种子太接近,所以只能直接生成
g.drawString(rand, 13 * i + 6, 16);
}

// 图象生效
g.dispose();

// 输出图象到页面
try {
ImageIO.write(image, "JPEG", response.getOutputStream());
} catch (Exception e) {
}
out.clear();
out = pageContext.pushBody();
%>


在login.jsp中 直接这样就可以产生啦

<TD class="td">验 证 码:</TD>
<TD class="td"><input name="checkNum" type="text" value="" id="checkNum" style="width: 80">
<img id="checkNumImage" src="${pageContext.request.contextPath}/image.jsp" height="19" align="absmiddle" onClick="changeCheckNum()"
title="点击换一张" style="cursor:hand"><s:fielderror fieldName="checkNum"/></TD>
</TR>
后台的验证代码
public String isLogin() throws UnsupportedEncodingException {
// 处理验证码:判断验证码输入的是否正确
boolean flag = SessionUtils.isCheckNum(request);
if (!flag) {
this.addFieldError("checkNum", "验证输入有误,请重新输入");
return "login";
}


// 处理用户名和密码输入的是否正确
String name = request.getParameter("name");
  String password = request.getParameter("password");
MD5keyBean m = new MD5keyBean();
  password = m.getkeyBeanofStr(password);
SysUser sysUser = sysUserService.findSysUserByNameAndPassword(name,
  password);
// 验证失败
if (sysUser == null) {
this.addFieldError("name", "用户名或者密码输入有误");
return "login";
  }
// 登录成功,放置当前的对象到session中
  SessionUtils.setSysUserToSession(request, sysUser);
// 处理Cookie
  addCookie(name, request.getParameter("password"), response, request);
return "main";
}


如果上面的一起都出来ok  有两种结果

第一 跳转到 main.jsp 也就是登录成功后的主界面

<action name="sysUserAction_*" class="com.crm.web.action.SysUserAction" method="{1}">
<result name="main">/WEB-INF/page/menu/main.jsp</result>


第二:登录不成功 (应该给相应的提示)

this.addFieldError("name", "用户名或者密码输入有误");

this.addFieldError("checkNum", "验证输入有误,请重新输入");

然后在login.jsp中得后面加入这句话

<s:fielderror fieldName="name"/>

<s:fielderror fieldName="checkNum"/>

因为全部走struts2 所以处理起来也就相对easy啦

当跳转到main.jsp 就可以做相应的操作啦 但是 还有一个问题

 如果他直接在地址栏中输入

http://localhost:8080/MyCRM/sys/sysUserAction_isLogin.do 也可以到主界面

为啦避免这种操作 出现啦所谓的粗粒度权限

思路:

     (1) 如果你是首次登录 需要输入用户名密码 当输入正确的时候 在跳转到主操作界面的时候 把你的信息放入到session中

     // 登录成功,放置当前的对象到session中
    SessionUtils.setSysUserToSession(request, sysUser);  这个对象里面放入啦很多信息  具体是什么后面讲~~

    (2)如果没有 进入登录界面还是直接在地址栏中输入 web程序中得 资源路径 就查看你session中有没有用户信息 如果没有 直接跳转到 登录界面

      怎样实现那 ? 哈哈都可能想到啦 对啦 就是filter过滤器

    过滤器是干什么的? 他就是 过滤你的每一个请求 和每一个相应

还是写代码把 ~~

public class SessionCheckUserFilter implements Filter {
private List<String> list;
public void init(FilterConfig filterConfig) throws ServletException {
//自己处理放置在资源文件,利用流读入
list=new ArrayList<String>();
list.add("/image.jsp");
list.add("/index.jsp");
list.add("/WEB-INF/page/login.jsp");
list.add("/sys/sysUserAction_isLogin.do");
///sys/sysUserAction_isLogin.do
}
public void doFilter(ServletRequest req, ServletResponse res,
FilterChain chain) throws IOException, ServletException {
HttpServletRequest request=(HttpServletRequest)req;
HttpServletResponse response=(HttpServletResponse)res;
String path=request.getServletPath(); 
//对 /image.jsp /index.jsp /login.jsp /sys/sysUserAction_isLogin路径过滤器要放行
if(list!=null&&list.contains(path)){
chain.doFilter(request, response);
return;
}
//获取当前的登陆用户
SysUser sysUser=SessionUtils.getSysUserFormSession(request); 
//如果用户!=null 表示用户已经登陆
if(sysUser!=null){
//放行
chain.doFilter(request, response);
}else{ //如果用户==null 表示用户没有登陆
//重定向到login.jsp(index.jsp)
response.sendRedirect(request.getContextPath());
}
}
public void destroy() {
}
}


记得一定要再web.xml文件中配置呀!!

<filter>
<filter-name>SessionCheckUserFilter</filter-name>
<filter-class>com.crm.filter.SessionCheckUserFilter</filter-class>
 </filter>
<filter-mapping>
<filter-name>SessionCheckUserFilter</filter-name>
  <url-pattern>*.jsp</url-pattern>
 </filter-mapping>
<filter-mapping>
<filter-name>SessionCheckUserFilter</filter-name>
  <url-pattern>*.do</url-pattern>
 </filter-mapping>


哦了 这样就可以啦 粗粒度就搞定啦

(2)细粒度权限 分两种 操作版 和菜单版本 有点困难 慢慢来啊

(2.1)操作版本的权限控制

为啦能更好的理解权限 还是有必要先说说 权限是什么 能干什么

大家都知道国家的领导人分很多 有什么 村长 县长 市长 省长 国长(主席) 球长(联合国主席)..

不同的人 有不同的权限 你说村长 能去 调动军队大利比亚吗?

公司也是 也分很多等级 如董事长ceo 经理  部门经理 人事部经理 财务部经理 一般员工等等~~~

我们做的crm系统也是   因为是web的程序  能有不同的人登陆 当然也就应该有不同的权限 不同的操作啦~~

好了 不多说啦  开始整~~

 第一:表级别的设计

  第一表: 用户表

   用户就是一个实实在在的 使用者  也就应该对应有相应的操作权限 也应该知道他属于什么级别(也就是档次) 还应该知道他输入那个部门

   在这里表示为sys_user表

CREATE TABLE `sys_user` (
`id` INTEGER(11) NOT NULL AUTO_INCREMENT, #编号 
`creator` VARCHAR(100) DEFAULT NULL, #创建人
`createTime` VARCHAR(19) DEFAULT NULL, #创建时间
`updater` VARCHAR(100) DEFAULT NULL, #修改人
`updateTime` VARCHAR(19) DEFAULT NULL, #修改时间
`remark` TEXT, #备注
`name` VARCHAR(100) DEFAULT NULL, #用户名
`cnname` VARCHAR(100) DEFAULT NULL, #中文名
`password` VARCHAR(100) DEFAULT NULL, #密码
`address` VARCHAR(200) DEFAULT NULL, #家庭地址
`telephone` VARCHAR(100) DEFAULT NULL, #家庭电话
`email` VARCHAR(100) DEFAULT NULL, #电子邮件
`beginDate` DATE DEFAULT NULL, #起始有效期
`endDate` DATE DEFAULT NULL, #终止有效期
`roleId` VARCHAR(36) NOT NULL, #操作权限组 (外键##################)
`groupId` INTEGER(11) NOT NULL DEFAULT '0', #所属部门 (外键##################)
`accessFileLevel` VARCHAR(50) DEFAULT NULL, #未命名
`status` VARCHAR(10) DEFAULT NULL, #状态
`commendMan` VARCHAR(50) DEFAULT NULL, #推荐人
`movetelePhone` VARCHAR(20) DEFAULT NULL, #移动电话
`nowAddress` VARCHAR(200) DEFAULT NULL, #现住宅地址
`nowtelePhone` VARCHAR(20) DEFAULT NULL, #现住宅电话
`identityCode` VARCHAR(20) DEFAULT NULL, #身份证号码
`insuranceCode` VARCHAR(20) DEFAULT NULL, #社会保险号
`instancyLinkman` VARCHAR(50) DEFAULT NULL, #紧急联系人
`instancytelePhone` VARCHAR(50) DEFAULT NULL, #紧急联系电话
`sex` VARCHAR(10) DEFAULT NULL, #性别
`birthday` DATE DEFAULT NULL, #出生日期
`personnelType` VARCHAR(50) DEFAULT NULL, #职员类别
`duty` VARCHAR(50) DEFAULT NULL, #职务
`workDate` DATE DEFAULT NULL, #入职时间
`highSchool` VARCHAR(100) DEFAULT NULL, #最高学历
`finishSchool` VARCHAR(100) DEFAULT NULL, #毕业学校
`finishSchoolDate` DATE DEFAULT NULL, #毕业时间
`consortName` VARCHAR(100) DEFAULT NULL, #配偶姓名
`youngoneName` VARCHAR(100) DEFAULT NULL, #子女姓名
`officetelePhone` VARCHAR(20) DEFAULT NULL, #办公电话
`consorttelePhone` VARCHAR(20) DEFAULT NULL, #配偶电话
`avocation` TEXT , #业余爱好
`consortCompany` VARCHAR(200) DEFAULT NULL, #配偶工作单位
`strongSuit` TEXT , #偏好特长
`commUniCate` TEXT , #信息沟通
`bringup` TEXT , #培训情况 
`organise` TEXT , #组织能力
`analyse` TEXT , #分析能力
`planing` TEXT , #计划能力
`empolder` TEXT , #人员开发
`relation` TEXT, #人际关系
PRIMARY KEY (`id`)
)


#设置外键约束
alter table sys_user
 add CONSTRAINT `sys_userfk_2` FOREIGN KEY (`groupId`) REFERENCES `sys_user_group` (`id`)
#设置外键约束
alter table sys_user
add CONSTRAINT `sys_userfk_3` FOREIGN KEY (`roleId`) REFERENCES `sys_role` (`id`)

因为每个用户都会有不同的权限 所以 用户和权限 是  一对多得关系  大家都知道一对多  就用外键来整理  一  ----通过外键 fk 指向外面的引用

因为每个用户都会有不同的部门 所有用户和部门 是 一对多得关系 大家都知道 该怎么办啦 通过外键 fk 来指向外面

 好啦设计第二张表:

用户组表 也就是部门表的拉~~ 因为后面会 有很多规定 所以 就不能叫department 啦 而叫 sys_user_group 因为这个表只是 用户的外表 所以狠esasy 自段也少

#部门信息表

CREATE TABLE `sys_user_group` (
`id` INTEGER(11) NOT NULL AUTO_INCREMENT, #编号
`remark` TEXT, #备注
`name` VARCHAR(100) DEFAULT NULL, #部门名称
`principal` VARCHAR(50) DEFAULT NULL, #部门负责人
`incumbent` VARCHAR(200) DEFAULT NULL, #部门职能
PRIMARY KEY (`id`)
)


因为狠easy 就不解释啦

设计第三张表 权限组表

#权限组表

CREATE TABLE `sys_role` (
`id` varchar(36), #编号
`remark` TEXT, #备注
`name` VARCHAR(100) DEFAULT NULL, #名称
PRIMARY KEY (`id`)
)


 有些人到这里可能就蒙啦 什么叫权限组啊 解释一下 一个人有 很多权限 比如说一个公民他 有 交税的权限(不交也不行啊~~) 还是吃饭的权限,找老婆的权限,找小三的权限(必须有钱啊~~) 而 如果不定义 一个组  来整理 这一些些权限 就不好整啦 ~~

  比如说 一个公司有两个人 这个人 刚进了 公司还不是狠信任他 就值给他 查看的权限 不给他修改的权限  就把这个权限用一个权限组 (比如中权限组名就readonly)  这里面放啦 能看不能写的啷个具体的权限  而老员工 有(read-write)的权限组  就能对这个进行操作啦 

 现在懂啦把 role 是角色的意思 也是权限组的意思

现在设置第四张表  操作(popedom)表

#操作表

CREATE TABLE sys_popedom
(
popedomModule VARCHAR(30), #模块名称
popedomPrivilege VARCHAR(30), #操作名称
sort INTEGER(11), #排序
title VARCHAR(200), #提示
popedomName VARCHAR(200), #标题
remark TEXT, #说明
PRIMARY KEY(popedomModule,popedomPrivilege)
)


这个表就是零散的定义一些操作 这个表 一般式实现写好的 

比如 下面的数据

这是零散的定义一些操作  要想真正的 给角色授予 适当的权限 还需要第三表 学过数据库的童鞋 都知道 多对多的关系 就是用第三章表来搞定

 因为一个角色 有 不同的操作    一个操作 可能有不同的角色在使用  不能说 你有吃饭的权限 别人就不能吃饭啦 ~~ 这样不合理

第五张表 就诞生啦 中间表sys_popedom_privilege(操作权限表) 

#操作权限表

CREATE TABLE sys_popedom_privilege
(
roleId VARCHAR(36), #权限组编号
popedomModule VARCHAR(30), #模块名称
popedomPrivilege VARCHAR(30), #操作名称
PRIMARY KEY(roleId,popedomModule,popedomPrivilege)
}


这里面 就是为了 方便 权限组 和操作 直接的关系 也就是 角色 和角色能干什么 的关系表

上面大家可能看到PRIMARY KEY(roleId,popedomModule,popedomPrivilege) 和PRIMARY KEY(popedomModule,popedomPrivilege) 不能理解

其实 这是联合主键 为了区分 所以不许加联合主键  还有为了以后在程序级别代码的实现容易 建议写规范点

module 里面是模块的名称 priedomprivlege 是具体能操作什么权限的的 名称(add啦..update.啊 save. 之类的)

------------------------------------------------------------------------------------

表级别的设计懂啦没?

答: 有点迷糊! 

没关系 以后多多练习就好啦

-------------------------------------------------------------------------------------------------------

(2.2)代码级别实现权限的控制

 还是从最开始开始整理

一个用户登录 会吧用户的名 和密码 输入到文本框 然后 通过 查数据库 可以把这个用户的信息查到

然后把这个用户放入到session当中  因为在用户表里面 有 权限组的id(也就是roleid 就知道啦 这个用户能干什么) 还有所属的部门id(也就是groupid就知道啦 这个用户 是什么部门的 应该操作什么模块) 

因为菜单级别的 权限我还没说 ! 你现在就当显示不同的菜单

当进入之后(先以admin登录 创建权限组和部门)

第一创建几个部门

 


然后创建几个角色 也就权限组


 



这里面 分一下 类 方便 理解  

第一 张鲲鹏 是  市场部的  应该对应市场部的权限

第二: 张保佳 是 人力资源部的 应该对应人力资源部的权限

第三: 本人 是销售部的 应该对应销售部的权限

开始授权 (说白啦 就是网 操作权限的表中插入数据 就是上面说的中间表)

开始整

这就是 授权的页面级别的 实现

但是真正功能级别的实现 还得 用代码来实现


因为csdn的日志 字符有限 下篇继续道来~~





评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值