Shiro安全框架

百度一下:

Apache Shiro(读作“sheeroh”,即日语“城”)是一个开源安全框架,提供身份验证、授权、密码学和会话管理。Shiro框架直观、易用,同时也能提供健壮的安全性。

  • Authentication:身份认证/登录,验证用户是不是拥有相应的身份;
  • Authorization:授权,即权限验证,验证某个已认证的用户是否拥有某个权限;即判断用户是否能做事情,常见的如:验证某个用户是否拥有某个角色。或者细粒度的验证某个用户对某个资源是否具有某个权限;
  • Session Manager:会话管理,即用户登录后就是一次会话,在没有退出之前,它的所有信息都在会话中;会话可以是普通JavaSE环境的,也可以是如Web环境的;
  • Cryptography:加密,保护数据的安全性,如密码加密存储到数据库,而不是明文存储;

Shiro安全框架交互过程:

  • Subject:主体,代表了当前“用户”,这个用户不一定是一个具体的人,与当前应用交互的任何东西都是Subject,如网络爬虫,机器人等;即一个抽象概念;所有Subject都绑定到SecurityManager,与Subject的所有交互都会委托给SecurityManager;可以把Subject认为是一个门面;SecurityManager才是实际的执行者;
  • SecurityManager:安全管理器;即所有与安全有关的操作都会与SecurityManager交互;且它管理着所有Subject;可以看出它是Shiro的核心,它负责与后边介绍的其他组件进行交互,如果学习过SpringMVC,你可以把它看成DispatcherServlet前端控制器;
  • Realm:域,Shiro从Realm获取安全数据(如用户、角色、权限),就是说SecurityManager要验证用户身份,那么它需要从Realm获取相应的用户进行比较以确定用户身份是否合法;也需要从Realm得到用户相应的角色/权限进行验证用户是否能进行操作;可以把Realm看成DataSource,即安全数据源。

程序员关注2个部分:如果获得Subject与如何定义一个符合规定的Realm(包括密码比较器)。

Shiro安全框架过滤器配置:

过滤器简称 对应的java类
anon org.apache.shiro.web.filter.authc.AnonymousFilter
authc org.apache.shiro.web.filter.authc.FormAuthenticationFilter
authcBasic org.apache.shiro.web.filter.authc.BasicHttpAuthenticationFilter
perms org.apache.shiro.web.filter.authz.PermissionsAuthorizationFilter
port org.apache.shiro.web.filter.authz.PortFilter
rest org.apache.shiro.web.filter.authz.HttpMethodPermissionFilter
roles org.apache.shiro.web.filter.authz.RolesAuthorizationFilter
ssl org.apache.shiro.web.filter.authz.SslFilter
user org.apache.shiro.web.filter.authc.UserFilter
logout org.apache.shiro.web.filter.authc.LogoutFilter

Shiro标签:

标签名称 标签条件(均是显示标签内容)
shiro:authenticated 登录之后
shiro:notAuthenticated 不在登录状态时
shiro:guest 用户在没有RememberMe时
shiro:user 用户在RememberMe时
shiro:hasAnyRoles name=”abc,123” 在有abc或者123角色时
shiro:hasRole name=”abc” 拥有角色abc
shiro:lacksRole name=”abc” 没有角色abc
shiro:hasPermission name=”abc” 拥有权限资源abc
shiro:lacksPermission name=”abc” 没有abc权限资源
shiro:principal 默认显示用户名称

使用Shiro

1,maven坐标的配置


在parent的工程中已经配置好了。

2,配置过滤器(放到struts的配置之前)

    <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>

3,在spring applicationContext.xml中记载shiro配置文件,放在事务管理器之前配置

这里就是产生代理的方式,应该放在事务代理器之前

<!--2.Shiro安全框架产生代理子类的方式: 使用cglib方式 --><aop:aspectj-autoproxy proxy-target-class="true" />

4,导入Shiro的配置文件

<?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:context="http://www.springframework.org/schema/context"   xmlns:tx="http://www.springframework.org/schema/tx"  xmlns:aop="http://www.springframework.org/schema/aop"  xsi:schemaLocation="http://www.springframework.org/schema/beans    http://www.springframework.org/schema/beans/spring-beans.xsd    http://www.springframework.org/schema/aop    http://www.springframework.org/schema/aop/spring-aop.xsd    http://www.springframework.org/schema/tx    http://www.springframework.org/schema/tx/spring-tx.xsd    http://www.springframework.org/schema/context    http://www.springframework.org/schema/context/spring-context.xsd"><description>Shiro的配置</description><!-- SecurityManager配置 --><!-- 配置Realm域 --><!-- 密码比较器 --><!-- 代理如何生成? 用工厂来生成Shiro的相关过滤器--><!-- 配置缓存:ehcache缓存 --><!-- 安全管理 --><bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager"><!-- Single realm app.  If you have multiple realms, use the 'realms' property instead. --><property name="realm" ref="authRealm"/><!-- 引用自定义的realm --><!-- 缓存 --><property name="cacheManager" ref="shiroEhcacheManager"/></bean><!-- 自定义权限认证 --><bean id="authRealm" class="cn.itcast.jk.shiro.AuthRealm"><property name="userService" ref="userService"/><!-- 自定义密码加密算法  --><property name="credentialsMatcher" ref="passwordMatcher"/></bean><!-- 设置密码加密策略 md5hash --><bean id="passwordMatcher" class="cn.itcast.jk.shiro.CustomCredentialsMatcher"/><!-- filter-name这个名字的值来自于web.xml中filter的名字 --><bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean"><property name="securityManager" ref="securityManager"/><!--登录页面  --><property name="loginUrl" value="/index.jsp"></property><!-- 登录成功后 -->      <property name="successUrl" value="/home.action"></property><property name="filterChainDefinitions"><!-- /**代表下面的多级目录也过滤 --><value>/index.jsp* = anon/home* = anon/sysadmin/login/login.jsp* = anon/sysadmin/login/logout.jsp* = anon/login* = anon/logout* = anon/components/** = anon/css/** = anon/images/** = anon/js/** = anon/make/** = anon/skin/** = anon/stat/** = anon/ufiles/** = anon/validator/** = anon/resource/** = anon/** = authc/*.* = authc</value></property></bean><!-- 用户授权/认证信息Cache, 采用EhCache  缓存 --><bean id="shiroEhcacheManager" class="org.apache.shiro.cache.ehcache.EhCacheManager"><property name="cacheManagerConfigFile" value="classpath:ehcache-shiro.xml"/></bean><!-- 保证实现了Shiro内部lifecycle函数的bean执行 --><bean id="lifecycleBeanPostProcessor" class="org.apache.shiro.spring.LifecycleBeanPostProcessor"/><!-- 生成代理,通过代理进行控制 --><bean class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator"depends-on="lifecycleBeanPostProcessor"><property name="proxyTargetClass" value="true"/></bean><!-- 安全管理器 --><bean class="org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor"><property name="securityManager" ref="securityManager"/></bean></beans>

做一点简单的描述吧。
在shiro的配置文件中,需要我我们手动处理的几个部分。

  • 安全管理器的配置
    需要注入我们自己的验证域和一个缓存管理。缓存管理比较简单,验证域应该就是我们比较和新的验证业务。

  • 缓存管理的内容如下,这个路径是需要我们手动更改的。

  • 自定义的认证域配置

    我们需要注入一个是用户的service,另一个是我们的密码比较器。
    我们看到出了注入下方的bean就是我们自定义的密码比较器。

5,先配置一些必要的注入等内容:

5.1,先导入缓存管理的文件

我们之前看到上图中的缓存管理注入的位置是“classpath:ehcache-shiro.xml”,所以我们就在resource中直接创建这个文件

<?xml version="1.0" encoding="UTF-8"?>
<ehcache updateCheck="false" name="shiroCache"><defaultCache
            maxElementsInMemory="10000"eternal="false"timeToIdleSeconds="120"timeToLiveSeconds="120"overflowToDisk="false"diskPersistent="false"diskExpiryThreadIntervalSeconds="120"/>
</ehcach

5.2,密码比较器

先用一个密码比较器的空模板,包的位置看一下注入的property

public class CustomCredentialsMatcher extends SimpleCredentialsMatcher {public boolean doCredentialsMatch(AuthenticationToken token,AuthenticationInfo info) {return false;}
}

5.3,AuthRealm的注入set方法。

public class AuthRealm extends AuthorizingRealm{public UserService userService;public void setUserService(UserService userService) {this.userService = userService;}//授权@Overrideprotected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection arg0) {// TODO Auto-generated method stubreturn null;}//认证@Overrideprotected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken arg0) throws AuthenticationException {// TODO Auto-generated method stubreturn null;}}

6,在Spring中导入Shiro的配置文件

<import resource="classpath:applicationContext-shiro.xml"></import> 

运行起来之后,点击部门管理会变成下面这个死样子

原因就是部门管理不能直接访问了,需要转到登录页,但是我们的系统目前没有登录功能,就只能回到这个首页了。
很难得,一个错误的页面验证了之前的工作都是正确的。保存一下草稿,丢了N回了。

解决一下,在fmain.jsp中添加一个script

<script type="text/javascript">if (self.location != top.location) {top.location = self.location;}
</script>

解释一下,由于shiro过滤器告诉失败会让我们的页面回到index.jsp,而我们顶层框架是部门管理。于是我们通过上述代码让顶层框架访问index.jsp。其原因是我们现在没有配合登录页面。
于是我们回到LoginAction类中,看到我们之前注释掉的代码,做一点修改。

public String login() throws Exception {// if(true){// String msg = "登录错误,请重新填写用户名密码!";// this.addActionError(msg);// throw new Exception(msg);// }// User user = new User(username, password);// User login = userService.login(user);// if (login != null) {// ActionContext.getContext().getValueStack().push(user);// session.put(SysConstant.CURRENT_USER_INFO, login); //记录session// return SUCCESS;// }// return "login";if (UtilFuns.isEmpty(username)) {return "login";}return SUCCESS;}

再看一下。

7,补充登录功能

7.1,密码比较器编写

7.1.1,导入md5hash工具类

在util中添加Encrypt工具类。

public class Encrypt {/** 散列算法一般用于生成数据的摘要信息,是一种不可逆的算法,一般适合存储密码之类的数据,* 常见的散列算法如MD5、SHA等。一般进行散列时最好提供一个salt(盐),比如加密密码“admin”,* 产生的散列值是“21232f297a57a5a743894a0e4a801fc3”,* 可以到一些md5解密网站很容易的通过散列值得到密码“admin”,* 即如果直接对密码进行散列相对来说破解更容易,此时我们可以加一些只有系统知道的干扰数据,* 如用户名和ID(即盐);这样散列的对象是“密码+用户名+ID”,这样生成的散列值相对来说更难破解。*///高强度加密算法,不可逆public static String md5(String password, String salt){return new Md5Hash(password,salt,2).toString();}
}

7.1.2,密码比较器的编写

public class CustomCredentialsMatcher extends SimpleCredentialsMatcher {// token:用户在页面输入的用户名密码,info代表从密码中得到的加数据public boolean doCredentialsMatch(AuthenticationToken token, AuthenticationInfo info) {// 向下转型UsernamePasswordToken usertoken = (UsernamePasswordToken) token;// 将用户输入的原始密码加密// 注意token.getPassword()拿到的是一个char[],不能直接用toString(),它底层实现不是我们想的直接字符串,只能强转// 用户名做为saltObject tokenCredentials = Encrypt.md5(String.valueOf(usertoken.getPassword()), usertoken.getUsername());//取得数据库中的密码数据Object accountCredentials = getCredentials(info);return equals(tokenCredentials, accountCredentials);}}

这里的使用的equals是父类提供的。

7.2,认证域的编写

package com.liuyang19900520.liussh.shiro;import java.util.ArrayList;
import java.util.List;
import java.util.Set;import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
import org.apache.shiro.authc.UsernamePasswordToken;
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 com.liuyang19900520.liussh.domain.Module;
import com.liuyang19900520.liussh.domain.Role;
import com.liuyang19900520.liussh.domain.User;
import com.liuyang19900520.liussh.service.UserService;public class AuthRealm extends AuthorizingRealm {// 注入public UserService userService;public void setUserService(UserService userService) {this.userService = userService;}// 授权@Overrideprotected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection arg0) {System.out.println("授权");// 首先根据name找到对象,对象的next就是一个userUser user = (User) arg0.fromRealm(this.getName()).iterator().next();// 根据realm的名字去找对应的realm。Set<Role> roles = user.getRoles();// 兑现导航List<String> permissions = new ArrayList<>();for (Role role : roles) {Set<Module> moudles = role.getModules();for (Module m : moudles) {// 这些标签在shiro:hasPermission的标签中会出现重复,// 但是标签的操作时用hascontents方法来进行,所以有重复也没有关系permissions.add(m.getName());}}SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();info.addStringPermissions(permissions);// 添加用户的权限--即我们的模块return info;}// 认证@Overrideprotected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken arg0) throws AuthenticationException {System.out.println("认证");// 向下转型(代表用户用在页面上输入的用户名与密码)UsernamePasswordToken upToken = (UsernamePasswordToken) arg0;// 调用业务方法,根据业务名查询String hql = "from User where userName=?";List<User> list = userService.find(hql, User.class, new String[] { upToken.getUsername() });if (list != null && list.size() > 0) {User user = list.get(0);AuthenticationInfo info = new SimpleAuthenticationInfo(user, user.getPassWord(), this.getName());return info;// 此处如果返回,就会进入到密码比较器。}return null;}}

7.3,编写loginAction写登录逻辑

// SSH传统登录方式public String login() throws Exception {if (UtilFuns.isEmpty(username)) {return "login";}try {// 得到SubjectSubject subject = SecurityUtils.getSubject();// 构造token(我们的username和password是页面上的)UsernamePasswordToken upToken = new UsernamePasswordToken(username, password);// 盗用shiro中的登录方法subject.login(upToken);// 当这一行代码执行时,就会自动跳转到比吗比较器// shiro有缓存,用户信息存在缓存中,User user = (User) subject.getPrincipal();// 将User放入sessoin中session.put(SysConstant.CURRENT_USER_INFO, user);} catch (Exception e) {request.put("errorInfo", "对不起,用户名密码错误");return "login";}return SUCCESS;}

8,顶部菜单释放

如果你也想问,为什么左侧的菜单不用加shiro标签么,那么请看一下左侧菜单的代码。

如图所示也就是说我们后续进到的模块都是通过user的角色到数据库查询出来的,不在需要shiro标签进行授权了,就是说菜单都是动态的。
所以我们要解开这个

还有值得注意的一点是,一旦JSP页面上出现shiro标签,就会执行授权方法。即认证域中的doGetAuthorizationInfo方法。

日常改错

输入正确的用户密码都不好使啊。这下验证得实在是太好了。
于是我重启了一下服务,JRbel真的不好使啊。于是成功了。

虽然权限看起来不同了,可是菜单怎么突然变多了这么多,并且还是重复的,一定是哪里出了问题。我们再来查询一下。
结果是清一下浏览器缓存,应该就没有问题了。

SSH入门项目-6-Shiro安全框架相关推荐

  1. Shiro安全框架【快速入门】就这一篇!

    Shiro 简介 照例又去官网扒了扒介绍: Apache Shiro™ is a powerful and easy-to-use Java security framework that perfo ...

  2. (转) shiro权限框架详解06-shiro与web项目整合(上)

    http://blog.csdn.net/facekbook/article/details/54947730 shiro和web项目整合,实现类似真实项目的应用 本文中使用的项目架构是springM ...

  3. 视频教程-Apache Shiro权限框架实战+项目案例视频课程-Java

    Apache Shiro权限框架实战+项目案例视频课程 拥有10余年项目实战经验. 2006-2011在nttdata从事对日软件开发类工作. 2011-2015在HP从事技术服务工作. 擅长于j2e ...

  4. Shiro安全框架【SpringBoot版】

    文章目录 Shiro安全框架 一. 入门概述 1.1.Shiro是什么 1.2.为什么使用Shiro 1.3.Shiro与Spring Security的区别 1.4.基本功能 1.4.1.主要功能 ...

  5. 在Spring MVC中使用Apache Shiro安全框架

    我们在这里将对一个集成了Spring MVC+Hibernate+Apache Shiro的项目进行了一个简单说明.这个项目将展示如何在Spring MVC 中使用Apache Shiro来构建我们的 ...

  6. 基于Springboot2.0的Dubbo入门项目(dubbo-spring-boot-starter)

    Dubbo是阿里巴巴公司开源的一个高性能优秀的服务框架,使得应用可通过高性能的 RPC 实现服务的输出和输入功能,可以和Spring框架无缝集成.最近半年来,Dubbo的得到了快速的维护,官方也推出了 ...

  7. shiro subject.getprincipal()为null_(变强、变秃)Java从零开始之Shiro安全框架

    Shiro安全框架 一.Shiro简介 二.Shiro架构图 三.Shiro涉及常见名词 四.Shiro配置文件详解 shiro.ini 文件放在 classpath 下 ,shiro 会自动查找.其 ...

  8. thymeleaf模板引擎shiro集成框架

    shiro权限框架.前端验证jsp设计.间tag它只能用于jsp系列模板引擎. 使用最近项目thymeleaf作为前端模板引擎,采用HTML档,未出台shiro的tag lib,假设你想利用这段时间s ...

  9. idea怎么运行eclipse的web项目_Apache Storm v2.0入门项目的开发、测试和运行(IDEA/Maven)...

    第一个Apache Storm v2.0流计算入门项目的开发.测试和运行(IDEA/Maven) 关于流计算框架Apache Storm最新版的安装,可以参考: 流计算框架-最新版Apache Sto ...

最新文章

  1. 关于BIO | NIO | AIO的讨论
  2. python字典操作添加_Python字典常见操作实例小结【定义、添加、删除、遍历】
  3. 2020-08-20如何获取AWS的Access Key ID 和 Secret Access Key (Unable to find credentials)
  4. 使用IB_DESIGNABLE与IBInspectable特性实现可在视图编辑器的功能栏中设置
  5. 09-spring学习-资源访问接口
  6. Openvswitch手册(5): VLAN and Bonding
  7. 【学习笔记】37、用正则表达式解析和提取数据
  8. ArcGIS 空间查询一例
  9. python中sign函数图片_python接口自动化-实现sign签名(MD5加密)
  10. 如何为 .NET Core 3.0 中 WPF 配置依赖注入 ?
  11. Qt线程和signal-slot
  12. NOIp 2014 联合权值 By cellur925
  13. Google 最高级别工程师的教育梦
  14. 洗清UI自动化鸡肋说的不白之冤
  15. JAVA_JDK下载与安装教程
  16. 2021年山东省安全员C证考试及山东省安全员C证模拟考试
  17. (转)iOS开发-常用第三方开源框架介绍(你了解的ios只是冰山一角)
  18. java 读取excel模板_java如何读取excel表格的信息,java读取excel模板
  19. 天融信防火墙tcpdump
  20. 阿里云机器学习平台PAI的视频介绍(其中tensorflow高级教程有tf的代码优化讲解)

热门文章

  1. VINS-Mono之IMU预积分,预积分误差、协方差及误差对状态量雅克比矩阵的递推方程的推导
  2. 大型数据库复习笔记——PL/SQL
  3. llt自发光_X射线激发荧光光谱仪的建立及闪烁晶体发光表征
  4. 如果客户只给我5分钟时间介绍EWM,怎么办?
  5. 解决Qt5.8加载qt_zh_CN.qm之后QMessageBox仍显示英文的问题
  6. springMVC数据校验
  7. CAN收发器PCA82C251与TJA1040的异同
  8. 区块链的梦该醒了吗?不,他们依然在想着感恩世界
  9. TCL通讯第三季度智能手机和平板电脑出货量显著增长;亚马逊云科技加速数据库服务在中国区域落地 | 全球TMT...
  10. 2022年第十一届认证杯数学中国数学建模国际赛小美赛:D题野生动物贸易是否应该长期禁止建模方案及代码实现