这几天自己做了一个小的demo,学习并使用了shiro框架用来管理我的登录与授权.学习这个框架到成功运用用了三天时间,前两天都是出于理解和踩坑阶段,第三天才真正开始撸起了代码,并自测成功.

首先我是通过这个这个网站学习的shiro

How2J 的 Java教程      http://how2j.cn/

这个网站非常好,涉及的知识面也特别的广,大家可以来收藏.

有了初步的了解后,我来捋一下我的shiro 的理解.

shiro是用来做登录管理和授权角色管理的,也就是说关于"登录"这部分都可以交给shiro去做.

打个比方: 只能登陆后才能访问的部分,可以比作是我们的家.登录页面,就是门禁系统,那shiro,就是这个门禁系统的核心,更形象一点说,这个shiro就是我们的管家(类似于钢铁侠的贾维斯).

我们可以通过配置贾维斯来控制哪些人(也就是代码里的链接)能进家里而不需要身份认证,哪些人必须要认证后才能进来.一旦贾维斯识别出这个人不是我们提前设置好的,那就统统给我滚回到门禁那里去做身份识别(也就是登录页面).这部分是shiro的登录认证管理.

通过了身份验证后,你就可以通过门禁系统而进入到我家里(也就是项目中的其他部分),并且我们的贾维斯能够记住你的身份,你的身份信息都被保存下来了.我们也可以随时随地都可以拿到你的身份信息.

进入我家后也不是所有的房间你都能进去,比如我的书房只有我的最亲的人才能进去.那当你想要进入我的书房时,贾维斯就开始识别你的身份,来看看你是不是我最亲的人.如果发现你不是,那你就没有权限进入书房,如果是,那就能顺利进入.这部分就是shiro的身份授权管理.

到这里,大家都对shiro是干嘛的有了一个基本的了解了.简单点说,shiro就是个拦截器,就像哨卡一样,拦住你,盘问你,识别你.不过有一点要注意,shiro只是来辅助你做这些事,至于哪些链接需要认证,哪些不需要,权限与角色的配置,这些都算是业务逻辑,必须由我们去完成才可以.

接下来,让我们来看看,要构建这么一个牛逼的安全管家应该怎么做.

由于现在用的比较多是SSM框架,所以这次我讲述的也都是在SSM框架环境下的shiro,其他环境下的我就不在这里赘述了.

首先导包.

就是ssm框架的那一套都导进去,然后 去shiro的官方http://shiro.apache.org/download.html上去下载 shiro的包,如果是maven项目,官网里也有pom中的各种依赖,复制粘贴就OK.

接下来搞SSM和shiro的配置文件.

配置文件有:

web.xml      管理配置文件,sprigmvc核心分发servlet以及shiro 过滤器的配置

spring-mvc.xml        springmvc的核心配置文件

spring-shiro.xml      shiro的核心配置文件,其实也可以与sping-mvc.xml写在一起

spring-mybatis.xml     管理数据库连接的

各配置的文件名不重要,重要的是里面的内容,并且我在这里列出要注意的和新增加的xml代码,常规的框架配置我就不再赘述.

一.首先是web.xml

因为我这里把shiro单独拿出来做一个xml配置文件了,所以在做xml引用时,我们要把这个文件加进去,由于我命名都是按照"spring-"为前缀,所以用了一个通配符,如果你的文件名不是这样的,那就分别写出来,就像注释里的那样.

<context-param><param-name>contextConfigLocation</param-name><param-value>classpath:spring-*.xml<!--classpath:applicationContext.xml,classpath:applicationContext-shiro.xml--></param-value></context-param><listener><listener-class>org.springframework.web.context.ContextLoaderListener</listener-class></listener>

然后配置shiro过滤器

 <!-- shiro过滤器定义 --><filter><filter-name>shiroFilter</filter-name><filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class><init-param><!-- 该值缺省为false,表示生命周期由SpringApplicationContext管理,设置为true则表示由ServletContainer管理 --><param-name>targetFilterLifecycle</param-name><param-value>true</param-value></init-param></filter><filter-mapping><filter-name>shiroFilter</filter-name><url-pattern>/*</url-pattern></filter-mapping>

二.spring-mvc.xml

1. springmvc的基本配置(这部分代码不展示了)
           2. 增加了对shiro的支持    这样可以在控制器Controller上,使用像@RequireRole 这样的注解,来表示某个方法必须有相关的角色才能访问
           3. 指定了异常处理类DefaultExceptionHandler,这样当访问没有权限的资源的时候,就会跳到统一的页面去显示错误信息,这条可有可无,看你的逻辑,如果需要可以配置

<!--启用shiro注解 --><beanclass="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator"depends-on="lifecycleBeanPostProcessor"><property name="proxyTargetClass" value="true" /></bean><beanclass="org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor"><property name="securityManager" ref="securityManager" /></bean><!-- 控制器异常处理 --><bean id="exceptionHandlerExceptionResolver" class="org.springframework.web.servlet.mvc.method.annotation.ExceptionHandlerExceptionResolver"></bean><bean class="com.how2java.exception.DefaultExceptionHandler"/> 

三.spring-shiro.xml

这部分很关键,我把所有的代码都贴上来

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns="http://www.springframework.org/schema/beans" xmlns:util="http://www.springframework.org/schema/util"xmlns:context="http://www.springframework.org/schema/context" xmlns:p="http://www.springframework.org/schema/p"xmlns:tx="http://www.springframework.org/schema/tx" xmlns:mvc="http://www.springframework.org/schema/mvc"xmlns:aop="http://www.springframework.org/schema/aop"xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans-4.0.xsd http://www.springframework.org/schema/txhttp://www.springframework.org/schema/tx/spring-tx-4.0.xsd http://www.springframework.org/schema/contexthttp://www.springframework.org/schema/context/spring-context-4.0.xsd http://www.springframework.org/schema/mvchttp://www.springframework.org/schema/mvc/spring-mvc.xsd http://www.springframework.org/schema/aophttp://www.springframework.org/schema/aop/spring-aop-4.0.xsd http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd"><context:component-scan base-package="com.blog.service"/><!-- 配置shiro的过滤器工厂类,id- shiroFilter要和我们在web.xml中配置的过滤器一致 --><bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean"><!-- 调用我们配置的权限管理器 --><property name="securityManager" ref="securityManager" /><!-- 配置我们的登录请求地址 --><property name="loginUrl" value="/login" /><!-- 如果您请求的资源不再您的权限范围,则跳转到/403请求地址 --><property name="unauthorizedUrl" value="/unauthorized" /><!-- 退出 --><property name="filters"><util:map><entry key="logout" value-ref="logoutFilter" /></util:map></property><!-- 权限配置 --><property name="filterChainDefinitions"><value><!-- anon表示此地址不需要任何权限即可访问 -->/loginBlogger=anon/index=anon/static/**=anon/doLogout=logout<!--所有的请求(除去配置的静态资源请求或请求地址为anon的请求)都要通过登录验证,如果未登录则跳到/login -->/** = authc</value></property></bean><!-- 退出过滤器 --><bean id="logoutFilter" class="org.apache.shiro.web.filter.authc.LogoutFilter"><property name="redirectUrl" value="/login" /></bean><!-- 会话ID生成器 --><bean id="sessionIdGenerator"class="org.apache.shiro.session.mgt.eis.JavaUuidSessionIdGenerator" /><!-- 会话Cookie模板 关闭浏览器立即失效 --><bean id="sessionIdCookie" class="org.apache.shiro.web.servlet.SimpleCookie"><constructor-arg value="sid" /><property name="httpOnly" value="true" /><property name="maxAge" value="-1" /></bean><!-- 会话DAO --><bean id="sessionDAO"class="org.apache.shiro.session.mgt.eis.EnterpriseCacheSessionDAO"><property name="sessionIdGenerator" ref="sessionIdGenerator" /></bean><!-- 会话验证调度器,每30分钟执行一次验证 ,设定会话超时及保存 --><bean name="sessionValidationScheduler"class="org.apache.shiro.session.mgt.ExecutorServiceSessionValidationScheduler"><property name="interval" value="1800000" /><property name="sessionManager" ref="sessionManager" /></bean><!-- 会话管理器 --><bean id="sessionManager"class="org.apache.shiro.web.session.mgt.DefaultWebSessionManager"><!-- 全局会话超时时间(单位毫秒),默认30分钟 --><property name="globalSessionTimeout" value="1800000" /><property name="deleteInvalidSessions" value="true" /><property name="sessionValidationSchedulerEnabled" value="true" /><property name="sessionValidationScheduler" ref="sessionValidationScheduler" /><property name="sessionDAO" ref="sessionDAO" /><property name="sessionIdCookieEnabled" value="true" /><property name="sessionIdCookie" ref="sessionIdCookie" /></bean><!-- 安全管理器 --><bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager"><property name="realm" ref="databaseRealm" /><property name="sessionManager" ref="sessionManager" /></bean><!-- 相当于调用SecurityUtils.setSecurityManager(securityManager) --><beanclass="org.springframework.beans.factory.config.MethodInvokingFactoryBean"><property name="staticMethod"value="org.apache.shiro.SecurityUtils.setSecurityManager" /><property name="arguments" ref="securityManager" /></bean><bean id="databaseRealm" class="com.blog.realm.DatabaseRealm"></bean><!-- 保证实现了Shiro内部lifecycle函数的bean执行 --><bean id="lifecycleBeanPostProcessor" class="org.apache.shiro.spring.LifecycleBeanPostProcessor" />
</beans> 

具体哪个是做什么的,我不多说.我会着重说几个.

<context:component-scan base-package="com.blog.service"/>

你会疑问了,这个为啥子在这里配呢.这个不应该springmvc.xml的配置文件里配吗? 没错,常规来说,确实是这样的.但是如果不在shiro.xml里配,到时候再shiro的realm中使用service层就会报错.可以看看这篇博客.

shiro框架,自定义realm注入service失败解决办法 - u33445687的博客 - CSDN博客
https://blog.csdn.net/u33445687/article/details/83617510

<!-- 配置shiro的过滤器工厂类,id- shiroFilter要和我们在web.xml中配置的过滤器一致 --><bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean"><!-- 调用我们配置的权限管理器 --><property name="securityManager" ref="securityManager" /><!-- 配置我们的登录请求地址 --><property name="loginUrl" value="/login" /><!-- 如果您请求的资源不再您的权限范围,则跳转到/403请求地址 --><property name="unauthorizedUrl" value="/unauthorized" /><!-- 退出 --><property name="filters"><util:map><entry key="logout" value-ref="logoutFilter" /></util:map></property><!-- 权限配置 --><property name="filterChainDefinitions"><value><!-- anon表示此地址不需要任何权限即可访问 -->/loginBlogger=anon/index=anon/static/**=anon/doLogout=logout<!--所有的请求(除去配置的静态资源请求或请求地址为anon的请求)都要通过登录验证,如果未登录则跳到/login -->/** = authc</value></property></bean>

这部分很重要,这部分就是告诉你的贾维斯,哪些人能过,哪些人是需要认证才能过的.以及退出指令等等.

<bean id="databaseRealm" class="com.blog.realm.DatabaseRealm"></bean>

这个是告诉shiro我们的realm是哪个.realm是什么,这个我们一会再说,你就先配置上就行.

至于其他的代码,都不用动,直接复制粘贴就行,当然了,那些配置具体是做什么的,可以自行去查找,网上都有.

四.spring-mybatis.xml    这个就是Mybatis的那一套, 没啥说的

我们看看登录效果哈

首先去登录,登陆失败,会到登录页面,并展示出错误信息.登录成功后,这时复制主页链接,点击安全退出后,在地址栏输入主页链接,会自动跳回登录页面.

接下来看看实现的代码

首先要有个登录页,这不必说了,表单的地址要为可通过的(即要在shiro.xml配置好)

后台登录的controller代码如下:

@Controller
@RequestMapping("")
public class LoginController {@RequestMapping("/loginBlogger")public String login(Model model,Blogger blogger) {//获取当前用户的shiro信息Subject currentUser = SecurityUtils.getSubject();  if (currentUser.isAuthenticated()) {return "redirect:/backgroundIndex";}//token安全令牌UsernamePasswordToken token = new UsernamePasswordToken(blogger.getUserName(), blogger.getPassword()); try {  //调用登录,会自动进入realmcurrentUser.login(token);Session session=currentUser.getSession();session.setAttribute("subject", currentUser);//登陆成功return "redirect:/backgroundIndex";//登陆失败.抛出异常} catch (AuthenticationException e) {  model.addAttribute("error", "验证失败");  return "/background/login.jsp"; }  }
}

这个LoginController就相当于门禁系统,他会去先判断有没有账号登录了,如果有登录,就会直接跳到主页去,如果没有,他就会拿着前台传过来的账号密码,来封装成一个安全令牌token,也可以理解为一个小纸条,上面有账号密码,然后拿着这个token去找我们的贾维斯,也就是realm,贾维斯开始判断,你这个过来的小纸条上的人可不可以通过.currentUser.login(token)执行时就会去realm,通过断点debug可以发现,他就会自动进入realm方法.

现在开始说这个shiro中最最关键的realm,英文翻译为"域",在我们这里就是可以理解为贾维斯.贾维斯会进行身份验证,会进行角色认证,也会进行授权认证(今天我们的例子中只有登录身份验证,等下期再说角色授权).

来看看realm的代码:着重去看登录与验证这部分

public class DatabaseRealm extends AuthorizingRealm {@Autowiredprivate ILoginService loginSerivce;/*** 角色与权限*/@Overrideprotected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {return null;}/*** 登录与验证*/@Overrideprotected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {//获取账号密码UsernamePasswordToken t = (UsernamePasswordToken) token;String userName= token.getPrincipal().toString();String password= new String( t.getPassword());//获取数据库中的密码Blogger blogger = loginSerivce.getBloggerByName(userName);//如果为空就是账号不存在,如果不相同就是密码错误,但是都抛出AuthenticationException,而不是抛出具体错误原因,免得给破解者提供帮助信息if(null==blogger.getPassword() || !blogger.getPassword().equals(password)) throw new AuthenticationException();//认证信息里存放账号密码, getName() 是当前Realm的继承方法,通常返回当前类名 :databaseRealmSimpleAuthenticationInfo a = new SimpleAuthenticationInfo(blogger,blogger.getPassword(),getName());return a;}}

逻辑很简单,就是获取到从前台传过来的token,也即是小纸条.然后得到纸条上的账号和密码,一般情况下,用户名都是唯一存在的,所以我们可以用用户名去数据库查找获得用户,获得后,再去进行判断.如果账号或密码不对,就要抛出异常.如果账号和密码匹对上了,我们就要把登陆的用户存放在SimpleAuthenticationInfo认证信息当中,意思就是告诉让贾维斯知道,这个人登陆成功了,也是为了方便我们在以后的业务逻辑当中随时能够获取当当前登录的人.

注意,SimpleAuthenticationInfo 这个对象中的第一个参数,我们尽量要存进去的是这个登录人的实例对象,也是方便以后获取,网上很多案例存的都是用户名.但是万一以后我们要修改账户信息的话,我还得从数据库查一遍,不如现在就存个实例对象,直接调用即可.

你也许会问,为啥在LoginController中执行currentUser.login(token)时就会走到这个realm中呢.?还记得我们在配置shiro.xml时配置过我们的realm路径不?

<bean id="databaseRealm" class="com.blog.realm.DatabaseRealm"></bean>

class中要写我们realm的全路径名,这样就能找到了.

至于退出的话,无非就是向后台发送一个关于退出的请求,就是在shiro.xml中配置的那个,发送后就会退出,并跳到相应的路径.

到这本次博客就基本结束了.

由于我的资历尚浅,道行不深,大部分也都是在网上找的,然后再加上自己的理解总结出来的.基本上也就是会用,至于为什么这么用,我自己还有很多很多不理解的地方.不管怎样,先跑起来,然后再一点一点地消化

目前我自己的这个小项目还没有涉及到角色权限这块,等我研究研究的再来写一篇关于权限与角色.

项目中的门禁管理者贾维斯———关于 Shiro 框架的 基本使用和基础配置,以及工作流程的生动解释相关推荐

  1. 【智能门禁系统设计】——项目需求分析(门禁终端软件)

    0.前言 门禁终端程序是运行在开发板上的程序,所以功能较少. 1.软件结构图 门禁终端软件:门禁终端软件主要使用QT+OpenCV实现,主要的功能就是提供密码.人脸.IC卡识别界面,然后根据用户输入的 ...

  2. 项目中基于Rest的Wcf服务发布以及iBatisNet框架的使用(下)

    iBatisNet框架的配置使用:iBatisNet框架的好处,有很多技术文档中有描述,在此只记录如何在项目中配置使用此框架.首先 在DAL层中添加引用:IBatisNet.DataMapper.dl ...

  3. 在spring MVC项目中集成Spring session redis (使用spring session框架,redis作为存储缓存)...

    2019独角兽企业重金招聘Python工程师标准>>> 1.为项目增加以来  pom.xml中使用 <!-- spring session 单点登录 --> //本项目使 ...

  4. java门禁系统项目开发实现

    文章目录 java门禁系统项目实现 一.项目目标和任务 二.项目结构 package sys Computer.java ControlSys.java Door.java InputEquip.ja ...

  5. 在系统二进制文件中检测到错误_门禁管理系统施工中常见的布线错误

    现在门禁系统已经深入到人们的生活中,门禁系统安装应用越来越广泛.但是门禁系统施工布线都需要注意哪些你了解吗?下面就门禁系统施工布线过程中的几大错误现象给大家提个醒. 一.用网络线布电锁锁到控制器的线! ...

  6. 51单片机项目之OLED显示多功能门禁系统(密码、刷卡、指纹、WIFI、蓝牙等)(一)硬件设计

    多功能门禁系统硬件设计 今天分享一款能够由个人独立完成的个人项目多功能门禁系统,具有以下功能: (1)指纹 1.指纹识别控制继电器开关电磁锁 2.添加指纹 3.删除指纹 (2)刷卡 1.RFID RC ...

  7. ESD门禁管理系统方案

    目录 一.系统概述... 2 1.1 前言... 2 1.2 系统设计总体要求... 2 1.3 系统设计原则... 3 1.4 设计依据... 3 1.5 系统特点... 5 二.ESD门禁管理系统 ...

  8. scada系统集成_专家 | 浅析地铁综合监控系统集成门禁系统

    目前国内省会及一.二线城市大力开展地铁建设,文章通过分析地铁综合监控系统及门禁系统软件和结构特点,浅析综合监控系统集成门禁系统的典型方案,并分析可行性. 关键词:综合监控系统:门禁系统:集成 中图分类 ...

  9. 高级货!Django实现基于人脸识别的门禁管理系统【源码】

    项目介绍 基于人脸识别的门禁管理系统 (Python+Django+RESTframework+JsonWebToken+Redis+Dlib) 该项目为宿舍门禁系统管理,并额外加入宿舍管理.水电费管 ...

  10. Python实现门禁管理系统(源码)

    项目介绍 基于人脸识别的门禁管理系统 (Python+Django+RESTframework+JsonWebToken+Redis+Dlib) 该项目为宿舍门禁系统管理,并额外加入宿舍管理.水电费管 ...

最新文章

  1. 文件流能转换格式吗_amr转换mp3格式文件
  2. java实现线性表的顺序存储
  3. docker network
  4. VTK:图像卷积用法实战
  5. 80后创业故事之:兄弟散伙,创业失败(转)
  6. PL/SQL异常处理
  7. 【LeetCode】剑指 Offer 46. 把数字翻译成字符串
  8. java 关于JDBC和DAO模式使用
  9. [排版题] 例4.2 叠框
  10. field list什么意思_Redis:我这21个灵魂拷问你拿什么挡?
  11. mac修改eclipse的内存配置
  12. fastDB核心心得
  13. android 锁屏代码分析,Android锁屏状态下的安全分析
  14. nginx配置前端网站
  15. 系统——windows10专业工作站版简单优化
  16. 【每日一道智力题】之 药瓶毒鼠鼠
  17. dcs常用的冗余方式_DCS的冗余
  18. 【数据分析】——分析方法
  19. 清华计算机系超算团队,关注 | 清华大学学生超算团队获国际超级计算机竞赛世界大学生超算竞赛总冠军...
  20. 不看不知道 轿车制造成本大揭密

热门文章

  1. C语言 队列的实现(链表实现)
  2. ElasticSearch查询模板
  3. librtmp源码详解
  4. mob AndroidStudio 短信SDK集成
  5. 基于MATLAB的人脸识别
  6. javaWeb上传文件(jsp上传文件)
  7. 大数据之实时数据分析之Apache Doris数据库
  8. TL431中文资料特性及应用
  9. xp系统怎么进pe修改计算机名,U盘装xp_教您怎样用u盘装xp系统
  10. 2013年最新十大xp系统下载排行榜-无极系统下载站