Shiro 权限认证核心:

POM:文件:

<!--shiro-all-->
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-all</artifactId>
<version>1.2.3</version>
</dependency>
<!-- 添加shrio-web支持 -->
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-web</artifactId>
<version>1.2.4</version>
</dependency>
<!-- 添加shrio-spring支持 -->
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-spring</artifactId>
<version>1.2.4</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.apache.shiro/shiro-ehcache -->
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-ehcache</artifactId>
<version>1.4.0</version>
</dependency>

WEB.XML:

<!--01.配置 Shiro 的 ShiroFilter-->
<filter>
<filter-name>shiroFilter</filter-name>
<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
<init-param>
<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-shiro.xml 配置文件:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:p="http://www.springframework.org/schema/p"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:jee="http://www.springframework.org/schema/jee"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.0.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd
http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-4.0.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.0.xsd"> <!-- 自定义Realm -->
<bean id="myRealm"
class="com.dsj.gdbd.controller.shiro.realm.MyRealm">
<property name="credentialsMatcher">
<bean
class="org.apache.shiro.authc.credential.HashedCredentialsMatcher">
<property name="hashAlgorithmName" value="MD5"></property>
<property name="hashIterations" value="1"></property>
</bean>
</property>
</bean> <bean id="securityManager"
class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">
<!-- 注入realm -->
<property name="realm" ref="myRealm" />
</bean> <!-- 开启Shiro注解 -->
<bean
class="org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor">
<property name="securityManager" ref="securityManager" />
</bean> <!-- 重写Shiro登录过滤器 -->
<bean id="loginAgainFilter"
class="com.dsj.gdbd.controller.shiro.filter.MyFormAuthenticationFilter"></bean>
<bean id="shiroFilter"
class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">
<!-- Shiro的核心安全接口,这个属性是必须的 -->
<property name="securityManager" ref="securityManager" /> <!-- 身份认证失败,则跳转到登录页面的配置(这里的路径与 form 表单路径一致,并且是 POST 请求) -->
<property name="loginUrl" value="/login/to_login" /> <!-- 权限认证失败,则跳转到指定页面 -->
<property name="unauthorizedUrl"
value="/login/to_unauthorized" /> <!-- 权限认证成功,则跳转到指定页面 -->
<property name="successUrl" value="/home/to_index" /> <property name="filters">
<map>
<entry key="mauthc" value-ref="loginAgainFilter" />
<entry key="logout">
<!-- 退出之后的重定向地址 -->
<bean class="org.apache.shiro.web.filter.authc.LogoutFilter">
<property name="redirectUrl" value="/login/to_login" />
</bean>
</entry>
</map>
</property> <property name="filterChainDefinitions">
<value> <!-- anon 表示可以匿名使用。 -->
/static/**=anon /login/to_login=mauthc
/login/logout=logout
/login/**=anon
<!-- authc表示需要认证(登录)才能使用 -->
/** = authc
</value>
</property>
</bean> </beans>

重写Shiro登录过滤器 :

package com.dsj.gdbd.controller.shiro.filter;

import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse; import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.subject.Subject;
import org.apache.shiro.web.filter.authc.FormAuthenticationFilter; public class MyFormAuthenticationFilter extends FormAuthenticationFilter {
//重写登录成功
@Override
protected boolean onLoginSuccess(AuthenticationToken token, Subject subject, ServletRequest request,
ServletResponse response) throws Exception {
//开启授权
subject.hasRole("*"); return super.onLoginSuccess(token, subject, request, response);
}
}

MyRealm.java  验证授权:

package com.dsj.gdbd.controller.shiro.realm;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List; import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
import org.apache.shiro.authc.UnknownAccountException;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired; import com.dsj.gdbd.pojo.MenuFunction;
import com.dsj.gdbd.pojo.RoleInfo;
import com.dsj.gdbd.pojo.UserInfo;
import com.dsj.gdbd.service.MenuFunctionService;
import com.dsj.gdbd.service.RoleInfoService;
import com.dsj.gdbd.service.UserInfoService;
import com.dsj.gdbd.utils.enums.DeleteStatusEnum; public class MyRealm extends AuthorizingRealm {
@Autowired
private UserInfoService userInfoService;
@Autowired
private RoleInfoService roleInfoService;
@Autowired
private MenuFunctionService menuFunctionService;
private final Logger LOGGER = LoggerFactory.getLogger(MyRealm.class); @SuppressWarnings("unchecked")
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) { /**
*
* 流程 1.根据用户user->2.获取角色id->3.根据角色id获取权限
*/
// 01、获取用户登陆ing
String realName = (String) principals.getPrimaryPrincipal();
LOGGER.info("realName{}", realName);
// 02、设置查询条件
UserInfo info = new UserInfo();
info.setRealName(realName);
info.setDelFlag(DeleteStatusEnum.NDEL.getValue());
// 03、查询对象信息
UserInfo userInfo = userInfoService.getInfo(info);
LOGGER.info("admin.id{}", userInfo.getId());
LOGGER.info("admin.name{}", userInfo.getUserName());
SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo();
// 04、获取用户下的所有角色
List<RoleInfo> rolelist = roleInfoService.getRoles(userInfo.getId());
// 获取所有角色的 Id
List<Long> rolesIds = new ArrayList<Long>();
for (RoleInfo item : rolelist) {
rolesIds.add(item.getId());
}
// 05、角色下所拥有的所有权限
List<MenuFunction> listMenus = menuFunctionService.getListMenus(rolesIds);
// 获取访问的权限
List<String> patterns = new ArrayList<String>();
for (MenuFunction item : listMenus) {
patterns.add(item.getPattern());
}
// 06、设置绑定 分类级别关系
List<MenuFunction> menuFunction = menuFunction(listMenus);
// 07、去掉空的权限
List<MenuFunction> notNullMenus = notNull(menuFunction);
// 08、权限菜单集合保存在Session 回话中
SecurityUtils.getSubject().getSession().setAttribute("menus", notNullMenus);
// 09、当前用户所拥有的所有权限保存在 session 会话中进行对比
SecurityUtils.getSubject().getSession().setAttribute("menusPatterns", patterns);
// 10、当前登录的用户信息
SecurityUtils.getSubject().getSession().setAttribute("sessionUser", userInfo);
// 11、将用户拥有的权限保存在 shiro中 用于后期页面的权限验证
authorizationInfo.addStringPermissions(
(List<String>) SecurityUtils.getSubject().getSession().getAttribute("menusPatterns"));
return authorizationInfo;
} /***
* 认证方法 验证账号密码
*/
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) {
System.out.println("进行验证了");
// 01、获取登录用户名
String realName = (String) authenticationToken.getPrincipal();
// 02、设置条件
UserInfo info = new UserInfo();
info.setRealName(realName);
info.setDelFlag(DeleteStatusEnum.NDEL.getValue());
// 03、查询对象信息
UserInfo userInfo = userInfoService.getInfo(info);
if (userInfo == null) {
throw new UnknownAccountException();
}
// 最后的比对需要交给安全管理器
// 三个参数进行初步的简单认证信息对象的包装(验证密码)
SimpleAuthenticationInfo authcInfo = new SimpleAuthenticationInfo(userInfo.getRealName(), userInfo.getUserPwd(),
this.getName());
return authcInfo;
} /***
* 执行遍历
*
* @param menus
* 所有权限列表集合
* @param list
* 指定角色查询到的 权限Id
* @return
*/
@SuppressWarnings("unused")
private List<MenuFunction> menuFunction(List<MenuFunction> menus) {
// 中转集合
List<MenuFunction> functions = null;
try {
functions = new ArrayList<MenuFunction>();
// 循环遍历菜单层级关系
// 循环遍历
for (MenuFunction item : menus) {
// 获取pid
long pid = item.getPid();
if (pid == 0) {
// 遍历一级分类
functions.add(item);
} else {
for (MenuFunction innerCate : menus) {
/***
* 外层循环 pid 没有的等于0 的话 获取当前对象的 id 作为一级
*/
Long id = innerCate.getId(); if (id == pid) {
innerCate.getChildren().add(item);
break;
}
}
}
} } catch (Exception e) {
LOGGER.error("循环遍历层级关系失败!!!" + e);
}
return functions;
} /***
* 去掉空的权限
*
* @param list
* @return
*/
private List<MenuFunction> notNull(List<MenuFunction> list) {
List<MenuFunction> menusList = null;
try {
// 去掉空的权限
menusList = new ArrayList<MenuFunction>();
for (int i = 0; i < list.size(); i++) {
if (list.get(i).getChildren().size() != 0) {
menusList.add(list.get(i));
notNull(list.get(i).getChildren());
}
}
} catch (Exception e) {
LOGGER.error("去除空的权限时意外出错!!!" + e);
}
return menusList;
}
}

Controller 关键代码:

package com.dsj.gdbd.controller.login;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
/***
* 登陆
* @author asus
*
*/
@Controller
@RequestMapping("login")
public class LoginController { /***
* 跳转登录页
* @return
*/
@RequestMapping("to_login")
public String login() { return "login/login";
}
}
package com.dsj.gdbd.controller.home;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping; @Controller
@RequestMapping("home")
public class HomeController { /***
* 跳转主页面
* @return
*/
@RequestMapping("to_index")
public String login() { return "home/welcome";
}
}

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

<%@ page contentType="text/html;charset=UTF-8"%>
<%@include file="/WEB-INF/jsp/common/taglibs.jspf"%>
<html lang="en">
<head>
<link rel="stylesheet" href="${ctx}/static/front/css/login/style.css">
<link rel="stylesheet"
href="${ctx}/static/front/bootstrap/3.3.7/css/bootstrap.min.css">
<script src="${ctx}/static/front/js/jquery.min.js"></script>
<script src="${ctx}/static/front/bootstrap/3.3.7/js/bootstrap.min.js"></script>
<script src='${ctx}/static/front/js/style.js'></script>
<script type="text/javascript">
var _ctx = '${ctx}';
</script>
<title>登录</title>
</head>
<style>
</style>
<body>
<!-- <div class="bj"> -->
<header>
<img src="${ctx}/static/front/images/login/logo.png" alt="">
</header>
<!-- </div> --> <div class="city">
<img src="${ctx}/static/front/images/login/4.png" alt="">
<div class="denglu">
<div class="titBian">
<span class="tit">用户登录</span> </div>
<form id="loginForm" action="${ctx }/login/to_login" method="post">
<div class="fengexian"></div>
<div class=" alert-danger dengLuTiShi" id="errorDiv">
<span class="dengLuTiShiTu glyphicon glyphicon-minus-sign"></span><span
id="error" class="cuo">${errormsg }</span>
</div> <div class="input-group name">
<span class="input-group-addon tx1" id="basic-addon1"><img
id="tx" class="tupian"
src="${ctx}/static/front/images/login/tuyiyi-com-0.png" alt=""></span>
<input type="text" id="phone" onclick="phone2()" name="username"
class="form-control" autocomplete="off" placeholder="请输入手机号或账号"
aria-describedby="basic-addon1"> <span
class="input-group-addon cha1" id="cha" onclick="qingkong()">X</span>
</div>
<div class="input-group password">
<span class="input-group-addon tx1" id="basic-addon2"><img
src="${ctx}/static/front/images/login/7.png" id="mm"
class="tupian" alt=""></span> <input type="password" id="mima"
name="password" class="form-control" onclick="mma()"
autocomplete="off" placeholder="请输入密码"
aria-describedby="basic-addon1">
</div>
<span class="wangjimima" onclick="wangji()">忘记密码</span>
<button id="login_btn" type="button" class="btn btn-primary btnDL">登录</button>
</form>
<%
//shiro 获取异常,判断异常类型
Object errorClass = request.getAttribute("shiroLoginFailure");
if ("org.apache.shiro.authc.IncorrectCredentialsException".equals(errorClass)) { request.setAttribute("errormsg", "用户名或密码错误");
}
if ("org.apache.shiro.authc.UnknownAccountException".equals(errorClass)) {
request.setAttribute("errormsg", "用户不存在或已禁用");
}
if ("com.dsj.data.shiro.filter.VerifyCodeException".equals(errorClass)) {
request.setAttribute("errormsg", "验证码不正确");
}
%> </div> </div>
<div class="yun">
<div class="kuanCont">
<a class="kuan">&nbsp;&nbsp;联系我们xxxxx&nbsp;&nbsp;</a> <a
class="kuan kuanLast">&nbsp;&nbsp;北京xxxxx技术服务有限公司&nbsp;&nbsp; </a>
</div>
</div>
<script type="text/javascript">
$(function() {
$("#login_btn").off().on("click", function() {
$("#loginForm").submit();
});
if ('${errormsg }' != '') {
var errorDiv = document.getElementById('errorDiv');
$("#error").html("${errormsg }");
errorDiv.style.visibility = 'visible';
} }) $(document).keydown(function(event) {
if (event.keyCode == 13) { //绑定回车
$('#login_btn').click();
}
});
</script>
<script src="${ctx }/static/back/login/login.js"></script>
</body>
</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. 三星DRAM+NAND FLASH 合成MCP芯片介绍及应用攻略

    转自:http://blog.csdn.net/gao5528/article/details/6256119 三星DRAM+NAND FLASH 合成MCP芯片介绍及应用攻略(K5系列产品篇) 一年 ...

  2. spring-test-dbunit的配置和使用

    1.数据源配置 <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" ...

  3. ObjC消息机制

    深入浅出ObjC之消息    罗朝辉(http://blog.csdn.net/kesalin) 在入门级别的ObjC 教程中,我们常对从C++或Java 或其他面向对象语言转过来的程序员说,ObjC ...

  4. usermod命令

    usermod 功能: 修改用户 常用参数:-c    账号说明-d    账号家目录-e    密码失效日期-g    主用户组GID-G    次用户组GID-l    账号名称-s    she ...

  5. Linux进程间通信(三) - 信号

    什么是信号 软中断信号(signal,又简称为信号)用来通知进程发生了异步事件.在软件层次上是对中断机制的一种模拟,在原理上,一个进程收到一个信号与处理器收到一个中断请求可以说是一样的.信号是进程间通 ...

  6. Elasticsearch集群问题,导致主master节点发现不了node节点

    个人博客:https://blog.sharedata.info/ 最新需要配置es集群采用5个分片和1个副片,正好是11台机器,而只保留一份备份所以只需要5*2=10台机器方案:1.1台作为mast ...

  7. c语言三元组

    // Triplet.cpp : 定义控制台应用程序的入口点.//#include "stdio.h"#include "stdlib.h"#define OK ...

  8. 大数进制转换 poj1220

    普通的做法,大数除小数. 复杂度o( log(n)*log(n) ),其实就是位数的平方. NUMBER BASE CONVERSION Time Limit: 1000MS   Memory Lim ...

  9. ElasticSearch(三十)基于scoll+bulk+索引别名实现零停机重建索引

    1.为什么要重建索引? 总结,一个type下的mapping中的filed不能被修改,所以如果需要修改,则需要重建索引 2.怎么zero time重建索引? 一个field的设置是不能被修改的,如果要 ...

  10. Linux安装过程记录信息

    全新的linux安装完成后,会在root目录下有一下三个文件,记录了Linux的安装细节 anaconda-ks.cfg 以Kickstart配置文件的格式记录安装过程中设置的选项信息 install ...