当前位置: 移动技术网 > IT编程>开发语言>Java > javaWeb用户权限控制简单实现过程

javaWeb用户权限控制简单实现过程

2019年07月22日  | 移动技术网IT编程  | 我要评论
最近在做一个网站类型的项目,要对用户的访问模块(权限)进行控制,所以设计并实现了一套简单的权限控制功能。  1. 数据库设计  用户:use

最近在做一个网站类型的项目,要对用户的访问模块(权限)进行控制,所以设计并实现了一套简单的权限控制功能。 

1. 数据库设计 

用户:users 

模块:modules

sql代码:

 /*
target server type : mysql
target server version : 50628
file encoding   : 65001

date: 2016-08-26 10:35:28
*/

set foreign_key_checks=0;

-- ----------------------------
-- table structure for `modules`
-- ----------------------------
drop table if exists `modules`;
create table `modules` (
 `id` int(10) not null auto_increment,
 `module` varchar(30) default null comment '模块',
 `pid` int(10) default null comment '上一级id',
 `level` int(4) default null comment '级别',
 primary key (`id`)
) engine=innodb default charset=utf8;

-- ----------------------------
-- records of modules
-- ----------------------------

-- ----------------------------
-- table structure for `users`
-- ----------------------------
drop table if exists `users`;
create table `users` (
 `user_code` varchar(10) not null comment '用户代码',
 `user_name` varchar(40) default null comment '用户名',
 `user_password` varchar(100) default null comment '密码',
 `qq` varchar(15) default null comment 'qq',
 `msn` varchar(50) default null comment 'msn',
 `demo` varchar(100) default null comment '备注',
 `auth_code` text comment '权限码',
 primary key (`user_code`)
) engine=innodb default charset=utf8;

-- ----------------------------
-- records of users
-- ---------------------------- 

1. 后端实现
 项目中用ssm+freemarker框架,把权限封装成权限树的数据结构,然后转成json格式。 
1) 展示层采用ztree树(setuserauthontree.html)

 <!doctype html>
<html>
<head>
<#include "common/res.html" />
<script src="${base.ctx}/js/layer-v2.1/laypage/laypage.js"></script>
<link href="${base.ctx}/js/layer-v2.1/laypage/skin/laypage.css" rel="stylesheet" type="text/css"/>
<script src="${base.ctx}/js/layer-v2.1/layer/layer.js"></script>
<!-- 引入树形菜单样式 -->
<link href="${base.ctx}/component/ztree/css/ztreestyle/ztreestyle.css" rel="stylesheet" type="text/css" />
<script type="text/javascript" src="${base.ctx}/component/ztree/js/jquery.ztree.core-3.5.js"></script>
<script type="text/javascript" src="${base.ctx}/component/ztree/js/jquery.ztree.excheck-3.5.js"></script>
<style type="text/css">
.blue-madison {
 border: 1px solid #7ca7cc;
 border-top: 0;
}

.caption {
 background-color: #578ebe;
 border-bottom: 0;
 padding: 0 10px;
 margin-bottom: 0;
 color: #fff;
}
</style>
</head>
<body>
 <div class="portlet-body" style="overflow-y:auto; width:400px; height:550px;">
 <div id="ztree" >
 <ul id="treedemo" class="ztree"></ul>
 </div>
 </div>
 <div class="form-actions">
 <div class="row">
 <div class="col-sm-12" align="center" style="margin-top: 5px">
 <button type='button' class="btn btn-primary"
  onclick="editmodle()">确定</button>
 <button type="button" class="btn btn-primary" id="cancel">关闭</button>
 </div>
 </div>
 </div>
 <script>
 $("document").ready(function() {
 $.ajax({
  type : "post",
  url : "${base.ctx}/setup/getuserrightmaskbyid",
  data:{"id":"${userid}"},
  datatype : "json",
  success : function(result) {
  ztreeobj = $.fn.ztree.init($("#treedemo"), setting,result.datas.data);
  ztreeobj.expandall(true);
  },
  error : function() {

  }
 });
 });

 //加载树
 var ztreeobj;
 // ztree 的参数配置,深入使用请参考 api 文档(setting 配置详解)
 var setting = {
 view : {
 //dblclickexpand : false,
 showline : true,     //是否显示节点间的连线 
 },
 check: {
  enable: true,
  //nocheckinherit: false,
  chkstyle: "checkbox",
  chkboxtype: { "y": "ps", "n": "ps" },
  //autochecktrigger: true
 },
 callback : {
 oncheck: ztreeoncheck,
 }
 };
 
 //checkbox点击的回调事件
 function ztreeoncheck(event, treeid, treenode) { 
 /* var ztree = $.fn.ztree.getztreeobj("treedemo"); 
   var changednodes = ztree.getchangecheckednodes(); 
   for ( var i=0 ; i < changednodes.length ; i++ ){ 
    var treenode = changednodes[i]; 
   } */ 
  }; 
 
 function editmodle(){
 var rootid=null;
  var midid=null;
  var minid=null;
 var treeobj = $.fn.ztree.getztreeobj("treedemo");
 var nodes = treeobj.getcheckednodes();
 
 for(var i=0;i<nodes.length;i++){
 if(nodes[i].level==0){
  rootid=rootid+","+nodes[i].id;
 }
 if(nodes[i].level==1){
  midid=midid+","+nodes[i].id;
 }
 if(nodes[i].level==2){
  minid=minid+","+nodes[i].id;
 }
 }
 if(rootid!=null){
 rootid=rootid.substring(5,rootid.length);
 }
 if(midid!=null){
 midid=midid.substring(5,midid.length);
 }
 if(minid!=null){
 minid=minid.substring(5,minid.length);
 }
 $.ajax({
  type : "post",
  url : "${base.ctx}/setup/updateuserrightmaskbyajax",
  datatype : "json",
  data:{"rootid":rootid,"midid":midid,"minid":minid,"userid":"${userid}"},
  success : function(result) {
  if(result=="1"){
  layer.msg("赋权成功!");
  settimeout(function(){top.dialog.get("set-dialog").close().remove();} , 600);
  }
  },
  error : function() {
  layer.msg("系统错误,请联系管理员!");
  }
 });
 }
 
 //关闭
 $("#cancel").click(function() {
 top.dialog.get("set-dialog").close().remove();
 });
 </script>
</body>
</html> 

展示效果如下:

2) controller控制层用springmvc 

在控制层把数据转成json格式,发到展示层。

 /**
 * @fun 获取分店用户权限
 * @author 皮锋
 * @date 2016/8/25
 * @param session
 * @param id
 * @param substoreid
 * @return
 */
 @requestmapping("getuserrightmaskbyid")
 @responsebody
 public object getuserrightmaskbyid(httpsession session,string id,string substoreid){
 substoreid=stringutils.isempty(substoreid)?string.valueof(session.getattribute("substoreid")):substoreid;
 //判断是酒店还是客栈
 list<map<string, object>> versionslist=this.setupservice.gethotelhotelversions(substoreid);
 object versions=versionslist.get(0).get("versions");
 map<string, object> hotelmap=new hashmap<string, object>();
 if((null!=versionslist)&&(versionslist.size()!=0)){ //list不为空
 if("complete".equals(versions)){ //酒店
 //查询酒店权限树
 hotelmap=this.rightmaskservice.getuserrightmaskontree(substoreid,id,"complete");
 }else if("simple".equals(versions)){ //客栈
 //查询客栈权限树
 hotelmap=this.rightmaskservice.getuserrightmaskontree(substoreid,id,"simple");
 }
 }
 map<string, object> resultmap = new hashmap<string, object>();
 resultmap.put("datas", hotelmap);
 
 return jsonobject.tojsonstring(resultmap, serializerfeature.writemapnullvalue);
 } 

3)service服务层把权限封装成满足ztree格式的树数据结构

 /**
 * @fun 获取分店用户权限
 * @author 皮锋
 * @date 2016/8/25
 * @param substoreid
 * @param id
 * @param versions
 * @return map<string, object>
 */
 @override
 public map<string, object> getuserrightmaskontree(string substoreid, string id, string versions) {
 map<string, object> userrightmask=this.irightmaskdao.getuserrightmaskbysubandid(substoreid,id);
 list<map<string, object>> listone = new arraylist<map<string,object>>();
 list<map<string, object>> listtwo = new arraylist<map<string,object>>();
 //list<map<string, object>> listthree = new arraylist<map<string,object>>();
 list<map<string, object>> resultlist = new arraylist<map<string, object>>();
 if(versions.equals("complete")){ //酒店
 listone = this.irightmaskdao.getrightmaskonhotelone();
 listtwo = this.irightmaskdao.getrightmaskonhoteltwo();
 //listthree = this.irightmaskdao.getrightmaskonhotelthree();
 packagingtotwotree(resultlist,listone,listtwo,userrightmask);
 }else if(versions.equals("simple")){ //客栈
 listone = this.irightmaskdao.getrightmaskontavernone();
 listtwo = this.irightmaskdao.getrightmaskontaverntwo();
 //listthree = this.irightmaskdao.getrightmaskontavernthree();
 packagingtotwotree(resultlist,listone,listtwo,userrightmask);
 }
 map<string, object> map = new hashmap<string, object>();
 map.put("data", resultlist);
 return map;
 }
/**
 * @function 封装一个一级树
 * @author 皮锋
 * @date 2016/8/26
 * @param resultlist
 * @param listone
 * @param authcode
 * @return void
 */
 private void packagingtoonetree(list<map<string, object>> resultlist,
 list<map<string, object>> listone, map<string, object> authcode) {
 for (int i = 0; i < listone.size(); i++) {
 map<string, object> rootmap = new hashmap<string, object>();
 rootmap.put("id", listone.get(i).get("id"));
 rootmap.put("name", listone.get(i).get("module"));
 if (validaterightmask(listone, authcode, i) != -1) {
 rootmap.put("checked", true);
 } else {
 rootmap.put("checked", false);
 }
 resultlist.add(rootmap);
 }
 }

 /**
 * @function 封装一个二级树
 * @author 皮锋
 * @date 2016/8/26
 * @param resultlist
 * @param listone
 * @param listtwo
 * @param authcode
 * @return void
 */
 private void packagingtotwotree(list<map<string, object>> resultlist,
 list<map<string, object>> listone,
 list<map<string, object>> listtwo, map<string, object> authcode) {
 for (int i = 0; i < listone.size(); i++) {

 list<map<string, object>> midlist = new arraylist<map<string, object>>();
 for (int j = 0; j < listtwo.size(); j++) {

 if (listtwo.get(j).get("pid").tostring()
  .equals(listone.get(i).get("id").tostring())) {

  list<map<string, object>> minlist = new arraylist<map<string, object>>();

  map<string, object> midmap = new hashmap<string, object>();
  midmap.put("id", listtwo.get(j).get("id"));
  midmap.put("name", listtwo.get(j).get("module"));
  midmap.put("children", minlist);
  if (validaterightmask(listtwo, authcode, j) != -1) {
  midmap.put("checked", true);
  } else {
  midmap.put("checked", false);
  }
  midlist.add(midmap);
 }
 }
 map<string, object> rootmap = new hashmap<string, object>();
 rootmap.put("id", listone.get(i).get("id"));
 rootmap.put("name", listone.get(i).get("module"));
 rootmap.put("children", midlist);
 if (validaterightmask(listone, authcode, i) != -1) {
 rootmap.put("checked", true);
 } else {
 rootmap.put("checked", false);
 }
 resultlist.add(rootmap);
 }
 }

 /**
 * @function 封装一个三级树
 * @author 皮锋
 * @date 2016/8/26
 * @param resultlist
 * @param listone
 * @param listtwo
 * @param listthree
 * @param authcode
 * @return void
 */
 private void packagingtothreetree(list<map<string, object>> resultlist,
 list<map<string, object>> listone,
 list<map<string, object>> listtwo,
 list<map<string, object>> listthree, map<string, object> authcode) {
 for (int i = 0; i < listone.size(); i++) {

 list<map<string, object>> midlist = new arraylist<map<string, object>>();
 for (int j = 0; j < listtwo.size(); j++) {

 if (listtwo.get(j).get("pid").tostring()
  .equals(listone.get(i).get("id").tostring())) {

  list<map<string, object>> minlist = new arraylist<map<string, object>>();

  for (int k = 0; k < listthree.size(); k++) {
  map<string, object> minmap = new hashmap<string, object>();
  if (listthree.get(k).get("pid").tostring()
  .equals(listtwo.get(j).get("id").tostring())) {
  minmap.put("id", listthree.get(k).get("id"));
  minmap.put("name", listthree.get(k).get("module"));
  if (validaterightmask(listthree, authcode, k) != -1) {
  minmap.put("checked", true);
  } else {
  minmap.put("checked", false);
  }
  minlist.add(minmap);
  }
  }
  map<string, object> midmap = new hashmap<string, object>();
  midmap.put("id", listtwo.get(j).get("id"));
  midmap.put("name", listtwo.get(j).get("module"));
  midmap.put("children", minlist);
  if (validaterightmask(listtwo, authcode, j) != -1) {
  midmap.put("checked", true);
  } else {
  midmap.put("checked", false);
  }
  midlist.add(midmap);
 }
 }
 map<string, object> rootmap = new hashmap<string, object>();
 rootmap.put("id", listone.get(i).get("id"));
 rootmap.put("name", listone.get(i).get("module"));
 rootmap.put("children", midlist);
 if (validaterightmask(listone, authcode, i) != -1) {
 rootmap.put("checked", true);
 } else {
 rootmap.put("checked", false);
 }
 resultlist.add(rootmap);
 }
 }

 /**
 * @function 验证authcode中是否有list中的权限码
 * @author 皮锋
 * @date 2016/8/26
 * @param list
 * @param authcode
 * @param i
 * @return int
 */
 private int validaterightmask(list<map<string, object>> list,
 map<string, object> authcode, int i) {
 string rightmask = authcode.get("auth_code") != null ? authcode.get(
 "auth_code").tostring() : "";
 if (!stringutils.isempty(rightmask)) {
 rightmask = rightmask.replace(";", ",");
 string[] arry = rightmask.split(",");
 for (int j = 0; j < arry.length; j++) {
 string arryrightmask = arry[j];
 string listrightmask = list.get(i).get("id").tostring();
 if (arryrightmask.equals(listrightmask)) {
  return 1;
 }
 }
 } else {
 return -1;
 }
 return -1;
 } 

4) dao层查询数据库获得用户权限 
a.在数据层按权限级别从modules表中分别拿出不同级别的权限 

select id,module,pid,level from modules where level='0' 
select id,module,pid,level from modules where level='1' 
select id,module,pid,level from modules where level='2'

b.在users表中拿出某用户的所有权限(权限码) 
select auth_code from users where user_code='pifeng' 
c.保存权限时不同级别之间的权限码用英式分号“;”隔开,同一级别之间的权限码用英式逗号“,”隔开。例如: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,36,37,27,28,29,30,31,32,33,34,35,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,56,57,58,59,60,61,62,63,64,133,65,66,67,68,69,70,71,72,73,74,75,126,127,128,129,130,131,76,77,78,79,80,81,82,83,84,85,86,87,88,99,124,134,135,136,140,141,89,90,91,92,93,94,95,96,97,98,137,138,139,100,101,102,103,106,107,132,108,109,110,111,112,113,114,115,116,125,117,118,119,120,121,122 

5)根据用户的权限码用freemarker标签控制页面功能模块是否显示 
a.freemarker在xml文件中的配置

 <bean id="freemarkerconfig"
   class="org.springframework.web.servlet.view.freemarker.freemarkerconfigurer">
  <!--模板加载路径-->
  <property name="templateloaderpath">
   <value>/web-inf/ftl/</value>
  </property>
  <property name="freemarkervariables">
   <map>
    <entry key="xml_escape" value-ref="fmxmlescape"/>
   </map>
  </property>
  <property name="freemarkersettings">
   <props>
    <prop key="tag_syntax">auto_detect</prop>
    <prop key="template_update_delay">0</prop>
    <prop key="default_encoding">utf-8</prop>
    <prop key="output_encoding">utf-8</prop>
    <prop key="locale">zh_cn</prop>
    <prop key="date_format">yyyy-mm-dd</prop>
    <prop key="time_format">hh:mm:ss</prop>
    <prop key="number_format">0.######</prop>
    <prop key="datetime_format">yyyy-mm-dd hh:mm:ss</prop>
    <!--空值处理-->
    <prop key="classic_compatible">true</prop>
    <!--自动导入ftl模板,并以“base”别名作为命名空间-->
    <prop key="auto_import">inc/spring.ftl as base</prop>
   </props>
  </property>
 </bean>

 <bean id="fmxmlescape" class="freemarker.template.utility.xmlescape"/>

 <bean id="freemarkerviewresolver"
   class="org.springframework.web.servlet.view.freemarker.freemarkerviewresolver">
  <property name="suffix" value=".html"/>
  <property name="cache" value="false"/>
  <property name="viewclass" value="org.springframework.web.servlet.view.freemarker.freemarkerview"/>
  <property name="contenttype" value="text/html;charset=utf-8"></property>
  <!--fixed exception:cannot expose session attribute 'substoreid' because of an existing model -->
  <property name="allowsessionoverride" value="true"/>
  <property name="exposerequestattributes" value="true"/>
  <property name="exposesessionattributes" value="true"/>
  <property name="exposespringmacrohelpers" value="true"/>
  <!-- 此变量值为pagecontext.request, 页面使用方法:request.contextpath -->
  <property name="requestcontextattribute" value="request"/>
  
  <property name="attributesmap"> 
   <map> 
    <!-- 定义freemarker方法的名称 --> 
    <entry key="menucall"> 
     <!-- 关联到我们之前定义的工具类 --> 
     <bean class="com.leike.util.menufunction" /> 
    </entry> 
   </map> 
  </property> 
 </bean> 

b.写个类继承templatemethodmodel类,实现freemarker自定义方法,用于实现控制页面模块是否显示 
登陆的时候把用户权限码存入session中,然后从session中取权限。下面是一个例子:

 public class menufunction implements templatemethodmodel{
 @override
 public object exec(list arg0) throws templatemodelexception { 
 int level = integer.valueof(arg0.get(0).tostring()); //模块等级
  int modelid=integer.valueof(arg0.get(1).tostring()); //模块id
  int count=0; //记录session是否有此模块的权限码
  httpservletrequest request = ((servletrequestattributes) requestcontextholder.getrequestattributes()).getrequest();
  httpsession session=request.getsession();
  object o = session.getattribute("info");
  if(o==null)
   return false;
  info info = (info) o;
  string authcode=info.getuser().getauthcode(); //权限码
  if(authcode.contains(";")){
  string[] masks=authcode.split(";");
  string[] m=masks[level].split(",");
  for (int i = 0; i < m.length; i++) {
  if(modelid==integer.parseint(m[i])){
  ++count;
  }else{
  count+=0;
  }
 }
  }
  if(count==0){
  return false;
  }else{
  return true;
  }
  
 }

} 

c.在页面使用freemarker标签,控制模块的显示隐藏 
menucall中的两个参数,第一个为模块等级,第二个为模块的id 
例如: 

<#if menucall(1,122)>
 <li style="line-height: 250%">
 <a href="#" id="booknew"><i class="glyphicon"></i>预订</a>
 </li>
</#if>

以上就是对用户的访问模块(权限)进行控制的大体实现。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持移动技术网。

如您对本文有疑问或者有任何想说的,请 点击进行留言回复,万千网友为您解惑!

相关文章:

验证码:
移动技术网