Apache Shiro 权限控制实战,权限控制Demo,SpringMVC + Mybatis + Shiro 项目下载

Shiro Demo 准备工作

运行前申明

请看完本页面的所有细节,对你掌握这个项目来说很重要,别一上来就搞,你不爽,我也不爽。

本项目需要一定的Java功底,需要对SpringMvc,Mybatis,有基本的了解,其次对Redis有了解和使用更佳。

本项目理论上,只需要一个Redis,然后一个Mysql和一个有Maven环境的开发工具即可运行起来。

运行步骤

Github下载源码(不定期更新和修复BUG),导入到Eclipse、MyEclipes、Idea类似开发工具。

解决编译错误,修改JDK为1.7以上(请勿使用工具自带JDK)。

在Mysql数据库中创建一个数据库,库名随便。

从项目/init/sql/下,先执行tables.sql创建表,再运行init.data.sql插入初始化数据。

再修改配置jdbc.properties把数据库链接改成您的。

安装Redis服务,如果您没用过,或者没安装,请看这里==>Redis 安装,以及注意事项都在里面有说明。

安装完毕后,修改配置:spring-cache.xml,如果是本地,无序修改,启动Redis,如对Redis不了解的同学,建议别设置密码。

运行项目,如果还有错误请参考异常信息,并解决,如果实在不能解决,请加QQ群交流,群需要付费5元,加群请看右侧菜单。

项目帐号和线上Demo一致:管理员帐号:admin,密码:sojson.com 如果密码错误,请用 sojson

线上Demo说明

Demo已经部署到线上,地址是:http://shiro.itboy.net

管理员帐号:admin,密码:sojson.com 如果密码错误,请用 sojson

你可以注册自己的帐号,然后用管理员赋权限给你自己的帐号,但是,每20分钟会把数据初始化一次。建议自己下载源码,让Demo跑起来,然后跑的更快,有问题加群解决。

Shiro Demo 源码下载

Shiro Demo 非Maven项目依赖包下载:点我下载

Github 0.1版本下载:https://github.com/baichengzhou/SpringMVC-Mybatis-shiro,(请下载0.2版本)

Github 0.2版本下载:https://github.com/baichengzhou/SpringMVC-Mybatis-Shiro-redis-0.2

Shiro Demo 0.2版本介绍:http://www.sojson.com/blog/165.html

Shiro Demo 0.2版本主要解决的问题为0.1版本出现的问题和BUG。

Shiro Demo 0.2版本为Shiro Demo 0.1的升级版本

PS:请选用0.2版本,这样你遇到的问题会比较少。

升级内容:

修复了些许BUG,优化了语法。

0.1版本限制较多,比如要部署到Tomcat Root下才能正常运行,就是用http://localhost:8080方式访问。

0.2版本可以采用目录访问,如:http://localhost:8080/shiro.demo/,默认项目名称为/shiro.demo/

Shiro 简介

Apache Shiro是Java的一个安全框架。我们经常看到它被拿来和SpringSecurity来对比。大部分人认为ShiroSecurity要简单。我的观点赞成一半一半吧。

首先Shiro确实和Security是同类型的框架,主要用来做安全,也就是我们俗称的权限校验(控制)。居多人对Shiro的定义为好入门。

我选型为Shiro,主要的原因扩展太easy了,而且我要的功能它都有。

本教程开发环境

本教程Jar包管理是Maven,所以如果是Maven项目下载Demo后可以直接使用,如果是普通的Java Web项目,那么请在下面下载所有依赖包。

本教程开发工具是Myecilpse8.5

本教程编码格式为UTF-8。

本教程JDK为1.7,请勿使用自带工具JDK。

本教程Mysql为5.3版本是以上。

Redis版本随意。

本教程Spring版本为4.2.5。

前端页面采用Bootstrap 3.2。

本教程包含的内容

SSM(SpringMVC+Spring+Mybatis)框架的增删改查(含分页),所以如果框架小白也是可以看看的。

View层主要是Freemarker,但是为了考虑到好多人还使用的是JSP,也有一个页面是用JSP实现的,并且框架支持Freemarker和JSP双View展示(优先找Freemarker)。

Shiro+Redis的集成,也提供Ehcache的依赖Jar。

Shiro初始权限动态加载。

Shiro自定义权限校验Filter定义,及功能实现。

ShiroAjax请求权限不满足,拦截后解决方案。

ShiroFreemarker标签使用。

ShiroJSP标签使用。

Shiro登录后跳转到最后一个访问的页面。

用户禁止登录Demo。

在线显示,在线用户管理(踢出登录)。

登录注册密码加密传输Demo(详细请见下面讲解)。

密码修改。

用户个人中心。

权限的增删改查。

角色的增删改查。

权限->角色->用户之间的关系维护。

管理员权限的自动添加(当有一个权限创建,自动添加到管理员角色下,保证管理员是最大权限)。

Spring定时任务数据化数据。

集成多种验证码(包括动态的gif验证码哦)。

一个帐号多处登录限制,踢出用户。

后续会陆陆续续升级... ...

一、SSM(SpringMVC + Mybatis)框架的增删改查(含分页)

本教程是SSM(SpringMVC+Spring+ Mybatis +Freemarker+ JSP)+ Shiro + Redis 做的整体Demo,其他框架需要自己自行解决,所以不做其他框架的讲解,其实是大同小异。

Controller==>Service(事务控制层) ==>Dao==>SqlMapper==>Mysql

二、View层 Freemarker,JSP

通用View层配置在spring-mvc.xml中的以【通用试图解析器】注释标注的区间配置。

三、Shiro + Redis 的集成,也提供Ehcache的依赖Jar。

Redis缓存配置主要在spring-cache.xml中。对应的所有Cache 相关Java代码在package:com.sojson.core.shiro.cache中

四、Shiro 初始权限动态加载。

我们一般是这么加载的。在spring-shiro.xml中配置

/** = anon

/page/login.jsp = anon

/page/register/* = anon

/page/index.jsp = authc

/page/addItem* = authc,roles[数据管理员]

/page/file* = authc,roleOR[普通用户,数据管理员]

/page/listItems* = authc,roleOR[数据管理员,普通用户]

/page/showItem* = authc,roleOR[数据管理员,普通用户]

/page/updateItem*=authc,roles[数据管理员]

本教程采用动态加载,你可以从数据库里读取然后拼接成shiro要的数据。

配置文件方式加载详细讲解:http://www.sojson.com/blog/148.html

五、Shiro 自定义权限校验Filter定义,及功能实现。

Shiro Filter在package:com.sojson.core.shiro.filter,具体配置在spring-shiro.xml中。定义了5个拦截器,具体功能看代码以及代码注释。

六、Shiro Ajax请求权限不满足,拦截后解决方案。

这里有一个前提,我们知道Ajax不能做页面redirect和forward跳转,所以Ajax请求假如没登录,那么这个请求给用户的感觉就是没有任何反应,而用户又不知道用户已经退出了。解决代码如下:

//Java代码,判断如果是Ajax请求,然后并且没登录,那么就给予返回JSON,login_status = 300,message = 当前用户没有登录!

if(ShiroFilterUtils.isAjax(request)){// ajax请求

MapresultMap=newHashMap();

LoggerUtils.debug(getClass(),"当前用户没有登录,并且是Ajax请求!");

resultMap.put("login_status","300");

resultMap.put("message","\u5F53\u524D\u7528\u6237\u6CA1\u6709\u767B\u5F55\uFF01");//当前用户没有登录!

ShiroFilterUtils.out(response,resultMap);

}

//前端代码

if(result.login_status==300){

layer.msg(result.message);//当前用户没有登录!

}

七、Shiro Freemarker标签使用。

Freemarker使用Shiro 标签的介绍:http://www.sojson.com/blog/143.html

八、Shiro JSP标签使用。

JSP使用Shiro 标签的介绍:http://www.sojson.com/blog/144.html

九、Shiro 登录后跳转到最后一个访问的页面。

Java中就可以这样获取上一个地址:

//上一个浏览的非Ajax的地址,在登录后,取得地址,如果不为null,那么就跳转过去。

Stringurl=(String)request.getAttribute(WebUtils.FORWARD_REQUEST_URI_ATTRIBUTE);

//shiro也有他的方法。详细看下面。

如果需要保存登录之前的Request信息,那么需要在Login拦截的Filter中先保存:

@Override

protectedbooleanonAccessDenied(ServletRequestrequest,ServletResponseresponse)

throwsException{

//保存Request和Response,登录后可以取到

saveRequestAndRedirectToLogin(request,response);

returnBoolean.FALSE;

}

//登录后,取到之前的Request中的一些信息。

SavedRequestsaveRequest=WebUtils.getSavedRequest(request);

saveRequest.getMethod();//之前的请求方法

saveRequest.getQueryString();//之前请求的条件

saveRequest.getRequestURI();//之前请求的路径

saveRequest.getRequestUrl();//之前请求的全路径

十、用户禁止登录Demo

这个功能其实是一个改变用户数据库表里的一个字段,本Demo中:1:有效,0:禁止登录

然后踢出用户登录状态。代码详细请查看CustomSessionManager.java类的forbidUserById(Long id, Long status)方法。

而再次登录的话,需要再登录,而登录的地方限制了用户状态为(0:禁止登录)的用户登录。

/**

* 查询要禁用的用户是否在线。

* @param id 用户ID

* @param status 用户状态

*/

publicvoidforbidUserById(Longid,Longstatus){

//获取所有在线用户

for(UserOnlineBobo:getAllUser()){

LonguserId=bo.getId();

//匹配用户ID

if(userId.equals(id)){

//获取用户Session

Sessionsession=shiroSessionRepository.getSession(bo.getSessionId());

//标记用户Session

SessionStatussessionStatus=(SessionStatus)session.getAttribute(SESSION_STATUS);

//是否踢出 true:有效,false:踢出。

sessionStatus.setOnlineStatus(status.intValue()==1);

//更新Session

customShiroSessionDAO.update(session);

}

}

}

十一、在线显示,在线用户管理(踢出登录)

上面的功能依赖这个功能。从Redis中获取所有有效的Session

/**

* 获取所有的有效Session用户

* @return

*/

publicListgetAllUser(){

//获取所有session

Collectionsessions=customShiroSessionDAO.getActiveSessions();

Listlist=newArrayList();

for(Sessionsession:sessions){

UserOnlineBobo=getSessionBo(session);

if(null!=bo){

list.add(bo);

}

}

returnlist;

}

踢出后,不能直接退出,要不然用户感觉莫名其妙。所有增加了一个Filter。SimpleAuthFilter.java如果标记为踢出,会提示用户。具体查看源码以及配合项目的使用。

十二、登录注册密码加密传输

这个地方好多人纠结的。比如密码过于简单,即使加密后也能破解。如我们把密码:123456,加密后就是:e10adc3949ba59abbe56e057f20f883e

这个很容易被识别,导致不安全,现在市面上的MD5破解其实就是把常用的数字,字母进行先加密,然后对比,美其名曰破解MD5。

那怎么能让用户即使使用很简单的密码,也发现不了?

本Demo的实现方式是:MD5(登录帐号 + “固定值” +  密码),把这个作为密码,这样,基本是不可能猜的出来。

//Java代码。UserManager.md5Pswd(UUser user);

/**

* 加工密码,和登录一致。

* @param user

* @return

*/

publicstaticUUsermd5Pswd(UUseruser){

//密码为  email + '#' + pswd,然后MD5

user.setPswd(md5Pswd(user.getEmail(),user.getPswd()));

returnuser;

}

/**

* 字符串返回值

* @param email

* @param pswd

* @return

*/

publicstaticStringmd5Pswd(Stringemail,Stringpswd){

pswd=String.format("%s#%s",email,pswd);

pswd=MathUtil.getMD5(pswd);

returnpswd;

}

//JS代码

varpswd=MD5(username+"#"+password);

十三、密码修改

不讲了,和上面原理一致,然后具体看Demo。

十四、用户个人中心

包含的功能有[个人资料,资料修改,密码修改,我的权限],具体看Demo。

十五、权限的增删改查。

本Demo的设计是遵循RBAC3的思想。http://www.sojson.com/blog/142.html

RBAC个人理解介绍:http://www.sojson.com/blog/141.html

具体实现看Demo。

十六、角色的增删改查

十七、权限->角色->用户之间的关系维护

把权限赋给角色。

把角色赋给用户。

十八、管理员权限的自动添加

这里每次添加一个权限,都会添加到“管理员”角色下,保证“管理员”角色拥有最大权限。

十九、Spring定时任务数据初始化

这个Demo因为是开放的,所以创建了一个定时任务。每20分钟执行一次,用Mysql存储过程重新创建表,重新插入初始化数据。

具体数据看项目中的init/sql下的tables.sql(初始化表),init.data.sql(初始化数据)。

//定时任务配置文件spring-timer.xml

//Java 代码 RoleServiceImpl.java

/**

* 每20分钟执行一次

*/

@Override

@Scheduled(cron="0 0/20 * * * ? ")

publicvoidinitData(){

roleMapper.initData();

}

二十、集成验证码

项目中package:com.sojson.common.utils.vcode包是验证码的封装包。

并且提供了一个VerifyCodeUtils.java 的验证码工具类。

使用方法参见:CommonController.java类中的getVCode()方法和getGifCode()方法。

验证码详细介绍

Java生成验证码合集(一)简单版

Java生成验证码合集(二)GJF版

二十一、一个帐号多处登录限制,踢出用户。

项目中我们会用到单点登录,还有用到单个账号怎么限制同时只能一个人在线?

Shiro教程(十一)Shiro 控制并发登录人数限制实现,登录踢出实现:http://www.sojson.com/blog/158.html

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 158,736评论 4 362
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,167评论 1 291
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,442评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,902评论 0 204
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,302评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,573评论 1 216
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,847评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,562评论 0 197
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,260评论 1 241
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,531评论 2 245
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,021评论 1 258
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,367评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,016评论 3 235
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,068评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,827评论 0 194
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,610评论 2 274
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,514评论 2 269

推荐阅读更多精彩内容