Shiro 权限认证核心:

POM:文件:

  1. <!--shiro-all-->
  2. <dependency>
  3. <groupId>org.apache.shiro</groupId>
  4. <artifactId>shiro-all</artifactId>
  5. <version>1.2.3</version>
  6. </dependency>
  7. <!-- 添加shrio-web支持 -->
  8. <dependency>
  9. <groupId>org.apache.shiro</groupId>
  10. <artifactId>shiro-web</artifactId>
  11. <version>1.2.4</version>
  12. </dependency>
  13. <!-- 添加shrio-spring支持 -->
  14. <dependency>
  15. <groupId>org.apache.shiro</groupId>
  16. <artifactId>shiro-spring</artifactId>
  17. <version>1.2.4</version>
  18. </dependency>
  19. <!-- https://mvnrepository.com/artifact/org.apache.shiro/shiro-ehcache -->
  20. <dependency>
  21. <groupId>org.apache.shiro</groupId>
  22. <artifactId>shiro-ehcache</artifactId>
  23. <version>1.4.0</version>
  24. </dependency>

WEB.XML:

  1. <!--01.配置 Shiro 的 ShiroFilter-->
  2. <filter>
  3. <filter-name>shiroFilter</filter-name>
  4. <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
  5. <init-param>
  6. <param-name>targetFilterLifecycle</param-name>
  7. <param-value>true</param-value>
  8. </init-param>
  9. </filter>
  10.  
  11. <filter-mapping>
  12. <filter-name>shiroFilter</filter-name>
  13. <url-pattern>/*</url-pattern>
  14. </filter-mapping>

spring-shiro.xml 配置文件:

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <beans xmlns="http://www.springframework.org/schema/beans"
  3. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  4. xmlns:p="http://www.springframework.org/schema/p"
  5. xmlns:aop="http://www.springframework.org/schema/aop"
  6. xmlns:context="http://www.springframework.org/schema/context"
  7. xmlns:jee="http://www.springframework.org/schema/jee"
  8. xmlns:tx="http://www.springframework.org/schema/tx"
  9. xsi:schemaLocation="
  10. http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.0.xsd
  11. http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
  12. http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd
  13. http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-4.0.xsd
  14. http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.0.xsd">
  15.  
  16. <!-- 自定义Realm -->
  17. <bean id="myRealm"
  18. class="com.dsj.gdbd.controller.shiro.realm.MyRealm">
  19. <property name="credentialsMatcher">
  20. <bean
  21. class="org.apache.shiro.authc.credential.HashedCredentialsMatcher">
  22. <property name="hashAlgorithmName" value="MD5"></property>
  23. <property name="hashIterations" value="1"></property>
  24. </bean>
  25. </property>
  26. </bean>
  27.  
  28. <bean id="securityManager"
  29. class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">
  30. <!-- 注入realm -->
  31. <property name="realm" ref="myRealm" />
  32. </bean>
  33.  
  34. <!-- 开启Shiro注解 -->
  35. <bean
  36. class="org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor">
  37. <property name="securityManager" ref="securityManager" />
  38. </bean>
  39.  
  40. <!-- 重写Shiro登录过滤器 -->
  41. <bean id="loginAgainFilter"
  42. class="com.dsj.gdbd.controller.shiro.filter.MyFormAuthenticationFilter"></bean>
  43. <bean id="shiroFilter"
  44. class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">
  45. <!-- Shiro的核心安全接口,这个属性是必须的 -->
  46. <property name="securityManager" ref="securityManager" />
  47.  
  48. <!-- 身份认证失败,则跳转到登录页面的配置(这里的路径与 form 表单路径一致,并且是 POST 请求) -->
  49. <property name="loginUrl" value="/login/to_login" />
  50.  
  51. <!-- 权限认证失败,则跳转到指定页面 -->
  52. <property name="unauthorizedUrl"
  53. value="/login/to_unauthorized" />
  54.  
  55. <!-- 权限认证成功,则跳转到指定页面 -->
  56. <property name="successUrl" value="/home/to_index" />
  57.  
  58. <property name="filters">
  59. <map>
  60. <entry key="mauthc" value-ref="loginAgainFilter" />
  61. <entry key="logout">
  62. <!-- 退出之后的重定向地址 -->
  63. <bean class="org.apache.shiro.web.filter.authc.LogoutFilter">
  64. <property name="redirectUrl" value="/login/to_login" />
  65. </bean>
  66. </entry>
  67. </map>
  68. </property>
  69.  
  70. <property name="filterChainDefinitions">
  71. <value>
  72.  
  73. <!-- anon 表示可以匿名使用。 -->
  74. /static/**=anon
  75.  
  76. /login/to_login=mauthc
  77. /login/logout=logout
  78. /login/**=anon
  79. <!-- authc表示需要认证(登录)才能使用 -->
  80. /** = authc
  81. </value>
  82. </property>
  83. </bean>
  84.  
  85. </beans>

重写Shiro登录过滤器 :

  1. package com.dsj.gdbd.controller.shiro.filter;
  2.  
  3. import javax.servlet.ServletRequest;
  4. import javax.servlet.ServletResponse;
  5.  
  6. import org.apache.shiro.authc.AuthenticationToken;
  7. import org.apache.shiro.subject.Subject;
  8. import org.apache.shiro.web.filter.authc.FormAuthenticationFilter;
  9.  
  10. public class MyFormAuthenticationFilter extends FormAuthenticationFilter {
  11. //重写登录成功
  12. @Override
  13. protected boolean onLoginSuccess(AuthenticationToken token, Subject subject, ServletRequest request,
  14. ServletResponse response) throws Exception {
  15. //开启授权
  16. subject.hasRole("*");
  17.  
  18. return super.onLoginSuccess(token, subject, request, response);
  19. }
  20. }

MyRealm.java  验证授权:

  1. package com.dsj.gdbd.controller.shiro.realm;
  2.  
  3. import java.util.ArrayList;
  4. import java.util.HashMap;
  5. import java.util.List;
  6.  
  7. import org.apache.shiro.SecurityUtils;
  8. import org.apache.shiro.authc.AuthenticationInfo;
  9. import org.apache.shiro.authc.AuthenticationToken;
  10. import org.apache.shiro.authc.SimpleAuthenticationInfo;
  11. import org.apache.shiro.authc.UnknownAccountException;
  12. import org.apache.shiro.authz.AuthorizationInfo;
  13. import org.apache.shiro.authz.SimpleAuthorizationInfo;
  14. import org.apache.shiro.realm.AuthorizingRealm;
  15. import org.apache.shiro.subject.PrincipalCollection;
  16. import org.slf4j.Logger;
  17. import org.slf4j.LoggerFactory;
  18. import org.springframework.beans.factory.annotation.Autowired;
  19.  
  20. import com.dsj.gdbd.pojo.MenuFunction;
  21. import com.dsj.gdbd.pojo.RoleInfo;
  22. import com.dsj.gdbd.pojo.UserInfo;
  23. import com.dsj.gdbd.service.MenuFunctionService;
  24. import com.dsj.gdbd.service.RoleInfoService;
  25. import com.dsj.gdbd.service.UserInfoService;
  26. import com.dsj.gdbd.utils.enums.DeleteStatusEnum;
  27.  
  28. public class MyRealm extends AuthorizingRealm {
  29. @Autowired
  30. private UserInfoService userInfoService;
  31. @Autowired
  32. private RoleInfoService roleInfoService;
  33. @Autowired
  34. private MenuFunctionService menuFunctionService;
  35. private final Logger LOGGER = LoggerFactory.getLogger(MyRealm.class);
  36.  
  37. @SuppressWarnings("unchecked")
  38. protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
  39.  
  40. /**
  41. *
  42. * 流程 1.根据用户user->2.获取角色id->3.根据角色id获取权限
  43. */
  44. // 01、获取用户登陆ing
  45. String realName = (String) principals.getPrimaryPrincipal();
  46. LOGGER.info("realName{}", realName);
  47. // 02、设置查询条件
  48. UserInfo info = new UserInfo();
  49. info.setRealName(realName);
  50. info.setDelFlag(DeleteStatusEnum.NDEL.getValue());
  51. // 03、查询对象信息
  52. UserInfo userInfo = userInfoService.getInfo(info);
  53. LOGGER.info("admin.id{}", userInfo.getId());
  54. LOGGER.info("admin.name{}", userInfo.getUserName());
  55. SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo();
  56. // 04、获取用户下的所有角色
  57. List<RoleInfo> rolelist = roleInfoService.getRoles(userInfo.getId());
  58. // 获取所有角色的 Id
  59. List<Long> rolesIds = new ArrayList<Long>();
  60. for (RoleInfo item : rolelist) {
  61. rolesIds.add(item.getId());
  62. }
  63. // 05、角色下所拥有的所有权限
  64. List<MenuFunction> listMenus = menuFunctionService.getListMenus(rolesIds);
  65. // 获取访问的权限
  66. List<String> patterns = new ArrayList<String>();
  67. for (MenuFunction item : listMenus) {
  68. patterns.add(item.getPattern());
  69. }
  70. // 06、设置绑定 分类级别关系
  71. List<MenuFunction> menuFunction = menuFunction(listMenus);
  72. // 07、去掉空的权限
  73. List<MenuFunction> notNullMenus = notNull(menuFunction);
  74. // 08、权限菜单集合保存在Session 回话中
  75. SecurityUtils.getSubject().getSession().setAttribute("menus", notNullMenus);
  76. // 09、当前用户所拥有的所有权限保存在 session 会话中进行对比
  77. SecurityUtils.getSubject().getSession().setAttribute("menusPatterns", patterns);
  78. // 10、当前登录的用户信息
  79. SecurityUtils.getSubject().getSession().setAttribute("sessionUser", userInfo);
  80. // 11、将用户拥有的权限保存在 shiro中 用于后期页面的权限验证
  81. authorizationInfo.addStringPermissions(
  82. (List<String>) SecurityUtils.getSubject().getSession().getAttribute("menusPatterns"));
  83. return authorizationInfo;
  84. }
  85.  
  86. /***
  87. * 认证方法 验证账号密码
  88. */
  89. protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) {
  90. System.out.println("进行验证了");
  91. // 01、获取登录用户名
  92. String realName = (String) authenticationToken.getPrincipal();
  93. // 02、设置条件
  94. UserInfo info = new UserInfo();
  95. info.setRealName(realName);
  96. info.setDelFlag(DeleteStatusEnum.NDEL.getValue());
  97. // 03、查询对象信息
  98. UserInfo userInfo = userInfoService.getInfo(info);
  99. if (userInfo == null) {
  100. throw new UnknownAccountException();
  101. }
  102. // 最后的比对需要交给安全管理器
  103. // 三个参数进行初步的简单认证信息对象的包装(验证密码)
  104. SimpleAuthenticationInfo authcInfo = new SimpleAuthenticationInfo(userInfo.getRealName(), userInfo.getUserPwd(),
  105. this.getName());
  106. return authcInfo;
  107. }
  108.  
  109. /***
  110. * 执行遍历
  111. *
  112. * @param menus
  113. * 所有权限列表集合
  114. * @param list
  115. * 指定角色查询到的 权限Id
  116. * @return
  117. */
  118. @SuppressWarnings("unused")
  119. private List<MenuFunction> menuFunction(List<MenuFunction> menus) {
  120. // 中转集合
  121. List<MenuFunction> functions = null;
  122. try {
  123. functions = new ArrayList<MenuFunction>();
  124. // 循环遍历菜单层级关系
  125. // 循环遍历
  126. for (MenuFunction item : menus) {
  127. // 获取pid
  128. long pid = item.getPid();
  129. if (pid == 0) {
  130. // 遍历一级分类
  131. functions.add(item);
  132. } else {
  133. for (MenuFunction innerCate : menus) {
  134. /***
  135. * 外层循环 pid 没有的等于0 的话 获取当前对象的 id 作为一级
  136. */
  137. Long id = innerCate.getId();
  138.  
  139. if (id == pid) {
  140. innerCate.getChildren().add(item);
  141. break;
  142. }
  143. }
  144. }
  145. }
  146.  
  147. } catch (Exception e) {
  148. LOGGER.error("循环遍历层级关系失败!!!" + e);
  149. }
  150. return functions;
  151. }
  152.  
  153. /***
  154. * 去掉空的权限
  155. *
  156. * @param list
  157. * @return
  158. */
  159. private List<MenuFunction> notNull(List<MenuFunction> list) {
  160. List<MenuFunction> menusList = null;
  161. try {
  162. // 去掉空的权限
  163. menusList = new ArrayList<MenuFunction>();
  164. for (int i = 0; i < list.size(); i++) {
  165. if (list.get(i).getChildren().size() != 0) {
  166. menusList.add(list.get(i));
  167. notNull(list.get(i).getChildren());
  168. }
  169. }
  170. } catch (Exception e) {
  171. LOGGER.error("去除空的权限时意外出错!!!" + e);
  172. }
  173. return menusList;
  174. }
  175. }

Controller 关键代码:

  1. package com.dsj.gdbd.controller.login;
  2.  
  3. import org.springframework.stereotype.Controller;
  4. import org.springframework.web.bind.annotation.RequestMapping;
  5. /***
  6. * 登陆
  7. * @author asus
  8. *
  9. */
  10. @Controller
  11. @RequestMapping("login")
  12. public class LoginController {
  13.  
  14. /***
  15. * 跳转登录页
  16. * @return
  17. */
  18. @RequestMapping("to_login")
  19. public String login() {
  20.  
  21. return "login/login";
  22. }
  23. }
  1. package com.dsj.gdbd.controller.home;
  2.  
  3. import org.springframework.stereotype.Controller;
  4. import org.springframework.web.bind.annotation.RequestMapping;
  5.  
  6. @Controller
  7. @RequestMapping("home")
  8. public class HomeController {
  9.  
  10. /***
  11. * 跳转主页面
  12. * @return
  13. */
  14. @RequestMapping("to_index")
  15. public String login() {
  16.  
  17. return "home/welcome";
  18. }
  19. }

login.jsp:登录页:(重点关注 form 表单 与 异常处理 )

  1. <%@ page contentType="text/html;charset=UTF-8"%>
  2. <%@include file="/WEB-INF/jsp/common/taglibs.jspf"%>
  3. <html lang="en">
  4. <head>
  5. <link rel="stylesheet" href="${ctx}/static/front/css/login/style.css">
  6. <link rel="stylesheet"
  7. href="${ctx}/static/front/bootstrap/3.3.7/css/bootstrap.min.css">
  8. <script src="${ctx}/static/front/js/jquery.min.js"></script>
  9. <script src="${ctx}/static/front/bootstrap/3.3.7/js/bootstrap.min.js"></script>
  10. <script src='${ctx}/static/front/js/style.js'></script>
  11. <script type="text/javascript">
  12. var _ctx = '${ctx}';
  13. </script>
  14. <title>登录</title>
  15. </head>
  16. <style>
  17. </style>
  18. <body>
  19. <!-- <div class="bj"> -->
  20. <header>
  21. <img src="${ctx}/static/front/images/login/logo.png" alt="">
  22. </header>
  23. <!-- </div> -->
  24.  
  25. <div class="city">
  26. <img src="${ctx}/static/front/images/login/4.png" alt="">
  27. <div class="denglu">
  28. <div class="titBian">
  29. <span class="tit">用户登录</span>
  30.  
  31. </div>
  32. <form id="loginForm" action="${ctx }/login/to_login" method="post">
  33. <div class="fengexian"></div>
  34. <div class=" alert-danger dengLuTiShi" id="errorDiv">
  35. <span class="dengLuTiShiTu glyphicon glyphicon-minus-sign"></span><span
  36. id="error" class="cuo">${errormsg }</span>
  37. </div>
  38.  
  39. <div class="input-group name">
  40. <span class="input-group-addon tx1" id="basic-addon1"><img
  41. id="tx" class="tupian"
  42. src="${ctx}/static/front/images/login/tuyiyi-com-0.png" alt=""></span>
  43. <input type="text" id="phone" onclick="phone2()" name="username"
  44. class="form-control" autocomplete="off" placeholder="请输入手机号或账号"
  45. aria-describedby="basic-addon1"> <span
  46. class="input-group-addon cha1" id="cha" onclick="qingkong()">X</span>
  47. </div>
  48. <div class="input-group password">
  49. <span class="input-group-addon tx1" id="basic-addon2"><img
  50. src="${ctx}/static/front/images/login/7.png" id="mm"
  51. class="tupian" alt=""></span> <input type="password" id="mima"
  52. name="password" class="form-control" onclick="mma()"
  53. autocomplete="off" placeholder="请输入密码"
  54. aria-describedby="basic-addon1">
  55. </div>
  56. <span class="wangjimima" onclick="wangji()">忘记密码</span>
  57. <button id="login_btn" type="button" class="btn btn-primary btnDL">登录</button>
  58. </form>
  59. <%
  60. //shiro 获取异常,判断异常类型
  61. Object errorClass = request.getAttribute("shiroLoginFailure");
  62. if ("org.apache.shiro.authc.IncorrectCredentialsException".equals(errorClass)) {
  63.  
  64. request.setAttribute("errormsg", "用户名或密码错误");
  65. }
  66. if ("org.apache.shiro.authc.UnknownAccountException".equals(errorClass)) {
  67. request.setAttribute("errormsg", "用户不存在或已禁用");
  68. }
  69. if ("com.dsj.data.shiro.filter.VerifyCodeException".equals(errorClass)) {
  70. request.setAttribute("errormsg", "验证码不正确");
  71. }
  72. %>
  73.  
  74. </div>
  75.  
  76. </div>
  77. <div class="yun">
  78. <div class="kuanCont">
  79. <a class="kuan">&nbsp;&nbsp;联系我们xxxxx&nbsp;&nbsp;</a> <a
  80. class="kuan kuanLast">&nbsp;&nbsp;北京xxxxx技术服务有限公司&nbsp;&nbsp; </a>
  81. </div>
  82. </div>
  83. <script type="text/javascript">
  84. $(function() {
  85. $("#login_btn").off().on("click", function() {
  86. $("#loginForm").submit();
  87. });
  88. if ('${errormsg }' != '') {
  89. var errorDiv = document.getElementById('errorDiv');
  90. $("#error").html("${errormsg }");
  91. errorDiv.style.visibility = 'visible';
  92. }
  93.  
  94. })
  95.  
  96. $(document).keydown(function(event) {
  97. if (event.keyCode == 13) { //绑定回车
  98. $('#login_btn').click();
  99. }
  100. });
  101. </script>
  102. <script src="${ctx }/static/back/login/login.js"></script>
  103. </body>
  104. </html>

其他 相关 Shiro 权限 Demo:案例Demo并不是很完整,你只需要拿走里面你需要的配置就好。

下载地址一  下载地址二

分享知识-快乐自己:Shrio 案例Demo概述的更多相关文章

  1. 分享知识-快乐自己:反射机制Demo解析

    Java-Reflect专题 基本反射简介: 1):JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象能够调用它的任意方法和属性;这种动态获取信息以及动 ...

  2. 分享知识-快乐自己:Mybatis 基础动态语句

    目录: User: package mlq.bean; /** * 用户实体类 */ public class User { private Integer uId; private String u ...

  3. 分享知识-快乐自己:Struts2(动态方法、动态结果、通配符、方法内部跳转、action跳转、OGNL 的使用及注意事项)

    这里主要以案例演示:涵盖以下知识点 1.动态方法调用:使用关键 符号 ! 进行操作   例如:/命名空间 ! 方法名 2.动态结果集:就是说,通过后台返回的结果 ${} 获取,重定向到符合预期的页面. ...

  4. 分享知识-快乐自己:全面解析 java注解实战指南

    请你在看这篇文章时,不要感到枯燥,从头到尾一行行看,代码一行行读,你一定会有所收获的. 问: 为什么学习注解? 学习注解有什么好处? 学完能做什么? 答: 1):能够读懂别人的代码,特别是框架相关的代 ...

  5. 分享知识-快乐自己:运行(wordcount)案例

    运行 wordcount 案例: 一):大数据(hadoop)初始化环境搭建 二):大数据(hadoop)环境搭建 三):运行wordcount案例 四):揭秘HDFS 五):揭秘MapReduce ...

  6. 分享知识-快乐自己:Nginx概述及如何使用

    概述: 什么是 Nginx? Nginx (engine x) 是一款轻量级的 Web 服务器 .反向代理服务器及电子邮件(IMAP/POP3)代理服务器. 什么是反向代理? 反向代理(Reverse ...

  7. 分享知识-快乐自己:SSH 整合 Demo

    楼主A: XML 版 SSH整合Demo https://github.com/MlqBeginner/BlogGardenWarehouse/blob/master/SSH%E6%95%B4%E5% ...

  8. 分享知识-快乐自己:初始 Struts2 (基本概念)及 搭建第一个Demo

    1):struts2 的基本概念: 1-1):Struts2 是什么? 1.Struts2是一个基于MVC设计模式的Web应用框架,它本质上相当于一个servlet,在MVC设计模式中,Struts2 ...

  9. 分享知识-快乐自己:搭建第一个 Hibernate (Demo)

    使用 Hibernate 完成持久化操作 七大 步骤: 1.读取并解析配置文件及映射文件: Configuration configuration=new Configuration().config ...

随机推荐

  1. NHibernate 组件基础 (第六篇)

    NHibernate 组件基础 (第六篇) 一.组件简介 组件(Component)可以理解为被一个对象所包含的对象而持久化,而并非一个实体.简单说来,假如数据库有FirstName,LastName ...

  2. Java并发编程(一)学习大纲

    (一)学习大纲 (二)线程与并发编程的概念 (三)线程安全.原子操作.复合操作.竞态条件.加锁机制(内置锁.重入) (四)对象的共享:可见性.失效数据.非原子的64位操作,加锁与可见性,volatil ...

  3. maven 依赖文件 pom.xml 编译 mvn compile 运行 不用mvn exec:java -Dexec.mainClass="hello.HelloWorld" 打成jar包 mvn package mvn install http://blog.csdn.net/yaya1943/article/details/48464371

    使用maven编译Java项目 http://blog.csdn.net/yaya1943/article/details/48464371  使用"mvn clean"命令清除编 ...

  4. easyui combobox 三级级联 input 两种实现

    /**<img src='${pageContext.request.contextPath}/images/block.png'/> * @param 默认载入 省市 */ $(func ...

  5. SourceTree超前一个版本,落后N个版本

    SourceTree超前一个版本,落后N个版本 在使用SourceTree的时候经常会遇见超前一个版本,落后N个版本的情况,遇见这种情况应该怎么办呢?   首先打开终端,最好是从SourceTree里 ...

  6. iOS开发 Xcode8 问题

      一.证书管理 用Xcode8打开工程后,比较明显的就是下图了,这个是苹果的新特性,可以帮助我们自动管理证书.建议大家勾选这个Automatically manage signing(Ps.但是在b ...

  7. ios推送服务,php服务端

    本文转载至http://my.oschina.net/AStar/blog/176531   生成证书 证书生成参考:https://parse.com/tutorials/ios-push-noti ...

  8. Idiomatic Phrases Game(图论最短路)

    Idiomatic Phrases Game Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/O ...

  9. ubuntu下操作端口的方法

    最简单的一个操作:sudo ufw status可检查防火墙的状态,我的返回的是:不活动 sudo ufw version防火墙版本: ufw 0.29-4ubuntu1 Copyright 2008 ...

  10. 算法调参 weight_ratio, weight_seqratio

    from openpyxl import Workbook import xlrd import time import Levenshtein as Le target_city_list = [' ...