本教程结合SSM(SpringMVC + Mybatis)框架讲解Shiro(Shiro是 Java 的一个安全框架。我们经常看到它被拿来和 Spring 的 Security 来对比。),讲解的内容有自定义Shiro拦截器,Shiro Freemarker标签,Shiro JSP标签,权限控制讲解,并提供Shiro Demo下载。
开发工具:Eclipse、MyEclipse、Idea等等。
依赖第三方:Mysql 5.0以上、Redis。
需要的配置:jdbc.properties中配置Mysql的信息、spring-cache.xml配置Redis 配置,如果是默认配置,就不用换,Redis Windows安装:http://www.sojson.com/blog/110.html。
注意:官方网站已经更新了第二个版本:http://www.sojson.com/shiro
申明:请看完本页面的所有细节,对你掌握这个项目来说很重要,别一上来就搞,你不爽,我也不爽。
本项目理论上,只需要一个Redis,然后一个Mysql和一个有Maven环境的开发工具即可运行起来。
Shiro Demo 非Maven项目依赖包下载:点我下载
Shiro Demo 源码下载下载:点我(云端下载)
Github 0.1版本下载:https://github.com/baichengzhou/SpringMVC-Mybatis-shiro
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,然后添加了一个功能--单个帐号登录限制问题,具体查看上面的介绍。
开发工具:Eclipse、MyEclipse、Idea等等。
依赖第三方:Mysql 5.0以上、Redis。
需要的配置:jdbc.properties中配置Mysql的信息、spring-cache.xml配置Redis 配置,如果是默认配置,就不用换,Redis Windows安装:http://www.sojson.com/blog/110.html。
Apache Shiro 是 Java 的一个安全框架。我们经常看到它被拿来和 Spring 的 Security 来对比。大部分人认为 Shiro 比 Security 要简单。我的观点赞成一半一半吧。
首先 Shiro 确实和 Security 是同类型的框架,主要用来做安全,也就是我们俗称的权限校验(控制)。居多人对 Shrio 的定义为好入门。
我选型为 Shiro ,主要的原因扩展太easy了,而且我要的功能它都有。
本教程Jar包管理是 Maven ,所以如果是 Maven 项目下载Demo后可以直接使用,如果是普通的Java Web项目,那么请在下面下载所有依赖包。
本教程开发工具是Myecilpse8.5。
本教程编码格式为UTF-8。
本教程JDK为1.7。
本教程Spring版本为4.2.5。
前端页面采用Bootstarp 3.2。
SSM(SpringMVC + Spring +Mybatis)框架的增删改查(含分页),所以如果框架小白也是可以看看的。
View层主要是Freemarker,但是为了考虑到好多人还使用的是JSP,也有一个页面是用JSP实现的,并且框架支持Freemarker 和JSP双View展示(优先找Freemarker)。
Shiro初始权限动态加载。
Shiro自定义权限校验Filter定义,及功能实现。
ShiroAjax请求权限不满足,拦截后解决方案。
ShiroFreemarker标签使用。
ShiroJSP标签使用。
Shiro登录后跳转到最后一个访问的页面。
用户禁止登录Demo。
在线显示,在线用户管理(踢出登录)。
登录注册密码加密传输Demo(详细请见下面讲解)。
密码修改。
用户个人中心。
权限的增删改查。
角色的增删改查。
权限->角色->用户之间的关系维护。
管理员权限的自动添加(当有一个权限创建,自动添加到管理员角色下,保证管理员是最大权限)。
Spring定时任务数据化数据。
集成多种验证码(包括动态的gif验证码哦)。
一个帐号多处登录限制,踢出用户。
后续会陆陆续续升级... ...
本教程是SSM(SpringMVC + Spring + Mybatis + Freemarker + JSP)+ Shiro + Redis 做的整体Demo,其他框架需要自己自行解决,所以不做其他框架的讲解,其实是大同小异。
Controller==>Service(事务控制层) ==>Dao==>SqlMapper==>Mysql
通用View层配置在spring-mvc.xml中的以【通用试图解析器】注释标注的区间配置。
Redis缓存配置主要在spring-cache.xml中。对应的所有Cache 相关 Java 代码在package:com.sojson.core.shiro.cache中
我们一般是这么加载的。在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要的数据。
<property name="filterChainDefinitions" value="#\{shiroManager.loadFilterChainDefinitions()\}"/>
配置文件方式加载详细讲解:http://www.sojson.com/blog/148.html
Shrio Filter在package:com.sojson.core.shiro.filter,具体配置在spring-shiro.xml中。定义了5个拦截器,具体功能看代码以及代码注释。
Shrio Filter在package:com.sojson.core.shiro.filter,具体配置在spring-shiro.xml中。定义了5个拦截器,具体功能看代码以及代码注释
<bean id="shiroManager" class="com.sojson.core.shiro.service.impl.ShiroManagerImpl"/> <bean id="login" class="com.sojson.core.shiro.filter.LoginFilter"/> <bean id="role" class="com.sojson.core.shiro.filter.RoleFilter"/> <bean id="permission" class="com.sojson.core.shiro.filter.PermissionFilter"/> <bean id="simple" class="com.sojson.core.shiro.filter.SimpleAuthFilter"/>
<property name="filters"> <util:map> <entry key="login" value-ref="login"></entry> <entry key="role" value-ref="role"></entry> <entry key="simple" value-ref="simple"></entry> <entry key="permission" value-ref="permission"></entry> </util:map> </property>
这里有一个前提,我们知道Ajax不能做页面redirect和forward跳转,所以Ajax请求假如没登录,那么这个请求给用户的感觉就是没有任何反应,而用户又不知道用户已经退出了。解决代码如下:
//Java代码,判断如果是Ajax请求,然后并且没登录,那么就给予返回JSON,login_status = 300,message = 当前用户没有登录! if (ShiroFilterUtils.isAjax(request)) {// ajax请求 MapresultMap = new HashMap(); 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);//当前用户没有登录! }
Freemarker使用Shiro 标签的介绍:http://www.sojson.com/blog/143.html
JSP使用Shiro 标签的介绍:http://www.sojson.com/blog/144.html
在 Java 中就可以这样获取上一个地址:
//上一个浏览的非Ajax的地址,在登录后,取得地址,如果不为null,那么就跳转过去。 String url = (String) request.getAttribute(WebUtils.FORWARD_REQUEST_URI_ATTRIBUTE); //shiro也有他的方法。详细看下面。
如果需要保存登录之前的Request信息,那么需要在Login拦截的Filter中先保存:
@Override protected boolean onAccessDenied(ServletRequest request, ServletResponse response) throws Exception { //保存Request和Response,登录后可以取到 saveRequestAndRedirectToLogin(request, response); return Boolean.FALSE ; } //登录后,取到之前的Request中的一些信息。 SavedRequest saveRequest = WebUtils.getSavedRequest(request); saveRequest.getMethod();//之前的请求方法 saveRequest.getQueryString();//之前请求的条件 saveRequest.getRequestURI();//之前请求的路径 saveRequest.getRequestUrl();//之前请求的全路径
这个功能其实是一个改变用户数据库表里的一个字段,本Demo中:1:有效,0:禁止登录
然后踢出用户登录状态。代码详细请查看CustomSessionManager.java类的forbidUserById(Long id, Long status)方法。
而再次登录的话,需要再登录,而登录的地方限制了用户状态为(0:禁止登录)的用户登录。
/** * 查询要禁用的用户是否在线。 * @param id用户ID * @param status用户状态 */ public void forbidUserById(Long id, Long status) { //获取所有在线用户 for(UserOnlineBo bo : getAllUser()){ Long userId = bo.getId(); //匹配用户ID if(userId.equals(id)){ //获取用户Session Session session = shiroSessionRepository.getSession(bo.getSessionId()); //标记用户Session SessionStatus sessionStatus = (SessionStatus) session.getAttribute(SESSION_STATUS); //是否踢出 true:有效,false:踢出。 sessionStatus.setOnlineStatus(status.intValue() == 1); //更新Session customShiroSessionDAO.update(session); } } }
上面的功能依赖这个功能。从Redis中获取所有有效的Session
/** * 获取所有的有效Session用户 * @return */ public List getAllUser() { //获取所有session Collection sessions = customShiroSessionDAO.getActiveSessions(); List list = new ArrayList(); for (Session session : sessions) { UserOnlineBo bo = getSessionBo(session); if(null != bo){ list.add(bo); } } return list; }
踢出后,不能直接退出,要不然用户感觉莫名其妙。所有增加了一个Filter。SimpleAuthFilter.java如果标记为踢出,会提示用户。具体查看源码以及配合项目的使用。
这个地方好多人纠结的。比如密码过于简单,即使加密后也能破解。如我们把密码:123456,加密后就是:e10adc3949ba59abbe56e057f20f883e
这个很容易被识别,导致不安全,现在市面上的MD5破解其实就是把常用的数字,字母进行先加密,然后对比,美其名曰破解MD5。
那怎么能让用户即使使用很简单的密码,也发现不了?
本Demo的实现方式是:MD5(登录帐号 + “固定值” + 密码),把这个作为密码,这样,基本是不可能猜的出来。
//Java代码。UserManager.md5Pswd(UUser user); /** * 加工密码,和登录一致。 * @param user * @return */ public static UUser md5Pswd(UUser user){ //密码为 email + '#' + pswd,然后MD5 user.setPswd(md5Pswd(user.getEmail(),user.getPswd())); return user; } /** * 字符串返回值 * @param email * @param pswd * @return */ public static String md5Pswd(String email ,String pswd){ pswd = String.format("%s#%s", email,pswd); pswd = MathUtil.getMD5(pswd); return pswd; }
//JS代码 var pswd = MD5(username +"#" + password);
不讲了,和上面原理一致,然后具体看Demo。
包含的功能有[个人资料,资料修改,密码修改,我的权限],具体看Demo。
本Demo的设计是遵循RBAC3的思想。http://www.sojson.com/blog/142.html
RBAC个人理解介绍:http://www.sojson.com/blog/141.html
具体实现看Demo。
把权限赋给角色。
把角色赋给用户。
这里每次添加一个权限,都会添加到“管理员”角色下,保证“管理员”角色拥有最大权限。
这个Demo因为是开放的,所以创建了一个定时任务。每20分钟执行一次,用Mysql存储过程重新创建表,重新插入初始化数据。
具体数据看项目中的init/sql下的tables.sql(初始化表),init.data.sql(初始化数据)
//定时任务配置文件spring-timer.xml//Java 代码 RoleServiceImpl.java /** * 每20分钟执行一次 */ @Override @Scheduled(cron = "0 0/20 * * * ? ") public void initData() { 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
不知道这样算不算侵权,但是假如侵权联系我删除 https://www.sojson.com/shiro
http://www.sojson.com/shiro http://blog.csdn.net/swingpyzf/article/details/46342023/ 转载于:https://www.cnblogs.com/gotodsp/p/6611533.html
本文向大家介绍Ajax 框架之SSM整合框架实现ajax校验,包括了Ajax 框架之SSM整合框架实现ajax校验的使用技巧和注意事项,需要的朋友参考一下 刚学习了ssm框架,ajax校验成功,分享下 1.导入jar包 2.配置spring-servlet.xml 3.控制器中用@ResponseBody实现返回json数据格式 4.页面中接收查询到的结果 实现结果就是以下这样的: 以上所述是小编
本文向大家介绍spring boot整合shiro安全框架过程解析,包括了spring boot整合shiro安全框架过程解析的使用技巧和注意事项,需要的朋友参考一下 这篇文章主要介绍了spring boot整合shiro安全框架过程解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 题记:在学习了springboot和thymeleaf之后,想
首先第一个版本,我们要先了解搭建一个库或者是一个给别人使用的小插件应该用一种什么样的格式. 首先我们需要创建一个闭包 (function(){ //code.. })(); 然后将我们所需要的代码和逻辑都写在里面避免全局变量的泛滥. 接着我们来看看我们第一版里的代码. (function(window,document) { var w = window, doc
使用GatewayWorker时开发者最关心的是如何与现有mvc框架(ThinkPHP Yii laravel等)整合,以下是官方推荐的整合方式。见示意图: 总体原则: 现有mvc框架项目与GatewayWorker独立部署互不干扰 所有的业务逻辑都由网站页面post/get到mvc框架中完成 GatewayWorker不接受客户端发来的数据,即GatewayWorker不处理任何业务逻辑,Gat
本文向大家介绍Aspectj框架实战案例详解,包括了Aspectj框架实战案例详解的使用技巧和注意事项,需要的朋友参考一下 本文实例讲述了Aspectj框架。分享给大家供大家参考,具体如下: 一 环境变量配置 CLASSPATH配置为: .;d:\aspectj1.8\lib\aspectjrt.jar;D:\Program\Java\jdk1.8.0_162\lib\dt.jar;D:\Prog
本文向大家介绍写简单的mvc框架实例讲解,包括了写简单的mvc框架实例讲解的使用技巧和注意事项,需要的朋友参考一下 这一章先把支持注解的功能加上,这样就不需要经常地修改配置文件了。 至于视图处理的地方,就还是先用json吧,找时间再写。 项目地址在:https://github.com/hjx601496320/aMvc 。 测试代码在:https://github.com/hjx60149632
本文向大家介绍讲解JavaScript的Backbone.js框架的MVC结构设计理念,包括了讲解JavaScript的Backbone.js框架的MVC结构设计理念的使用技巧和注意事项,需要的朋友参考一下 什么是Backbone.js? Backbone.js是十大JS框架之首,Backbone.js 是一个重量级js MVC 应用框架,也是js MVC框架的鼻祖。它通过Models数据模型进
本文向大家介绍ABP框架的体系结构及模块系统讲解,包括了ABP框架的体系结构及模块系统讲解的使用技巧和注意事项,需要的朋友参考一下 DDD分层 为了减少复杂性和提高代码的可重用性,采用分层架构是一种被广泛接受的技术。 为了实现分层的体系结构,ABP遵循DDD(领域驱动设计)的原则,将分为四个层次: 展现层(Presentation):提供一个用户界面,实现用户交互操作。 应用层(Applicati