方法/步骤

  1. 1

    web.xml添加配置

    <!-- shiro过滤器 -->

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

  2. 2

    shiro与spring整合配置

    <!-- 使用shiro安全检查注解 -->

    <bean class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator" depends-on="lifecycleBeanPostProcessor" />

    <bean class="org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor">

    <property name="securityManager" ref="securityManager" />

    </bean>

    <!-- shiro的生命周期处理器 -->

    <bean id="lifecycleBeanPostProcessor" class="org.apache.shiro.spring.LifecycleBeanPostProcessor" />

    <!-- shiro自带的密码匹配器(用来校验密码足够了) -->

    <bean id="credentialsMatcher" class="org.apache.shiro.authc.credential.SimpleCredentialsMatcher"></bean>

    <!-- security datasource: -->

    <bean id="myRealm" class="cc.eguid.service.shiro.MyRealm">

    <property name="credentialsMatcher" ref="credentialsMatcher"/><!-- 密码匹配器 -->

    <property name="cachingEnabled" value="false"/><!-- 禁止缓存 -->

    </bean>

    <!-- 安全管理器 -->

    <bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">

    <property name="realm" ref="myRealm" />

    </bean>

    <!-- shiro过滤器 -->

    <bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">

    <!-- 配置安全管理器 -->

    <property name="securityManager" ref="securityManager" />

    <!-- 身份认证失败跳转的地址 -->

    <property name="loginUrl" value="/login/" />

    <!-- 身份认证成功跳转的地址 -->

    <property name="successUrl" value="/" />

    <!-- 权限认证失败跳转的地址 -->

    <property name="unauthorizedUrl" value="/login/unauthorized" />

    <property name="filterChainDefinitions">

    <!--anon 表示匿名访问,不需要认证以及授权 -->

    <!--authc表示需要认证 没有进行身份认证是不能进行访问的 -->

    <!--authc,roles[admin]表示是admin角色的用户才能访问 -->

    <value>

    /static/** = anon

    /login/** = anon

    /common/** = anon

    /admin/** = authc,roles[admin]

    /* = authc

    /** = authc

    </value>

    </property>

    </bean>

  3. 3

    realm和自定义密码校验器实现

    public class MyRealm extends AuthorizingRealm{

    Logger log=Logger.getLogger(MyRealm.class);

    @Autowired

    private UserService userService;//这是自己实现的用户信息操作类,实现用户信息,用户角色信息、用户权限信息查询功能

    @Override

    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {

    UserInfo user = (UserInfo) principals.getPrimaryPrincipal();

    SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();

    // 查询角色信息

    Collection<String> roles = userService.findRoles(user);

    info.addRoles(roles);

    log.info("shiro获取用户所属角色列表:"+roles);

    // 查询权限信息

    Collection<String> permissions = userService.findPermissions(user.getSystemuserid());

    info.addStringPermissions(permissions);

    log.info("shiro获取用户权限列表:"+permissions);

    return info;

    }

    @Override

    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token)throws AuthenticationException{

    //用户输入的用户名密码

    String loginname=  token.getPrincipal().toString();

    Object password=token.getCredentials();

    log.info("shiro正在处理尝试登录的用户信息:"+loginname+",密码:"+new String((char[])password));

    //数据库中的用户信息

    UserInfo user =userService.queryUserInfoByLoginName(loginname);

    if(user==null||CommonUtil.isNull(user.getLoginusername(),user.getPassword(),user.getSystemuserid())){

    return null;

    }

    log.info("shiro获取到当前用户尝试登录的真实数据:"+user.getLoginusername()+",密码:"+user.getPassword());

    //数据库中的正确的账户信息

    AuthenticationInfo accountInfo =new SimpleAuthenticationInfo(user, user.getPassword(),getName());

    //自己获取密码验证器(由于shiro实现的密码校验方法是密码错误会直接抛异常,不采用,所以改成直接手动校验)

    CredentialsMatcher matcher=getCredentialsMatcher();

    if(matcher==null){

    log.error("没有配置密码匹配器");

    return null;

    }

    //校验密码

    if(matcher.doCredentialsMatch(token,accountInfo)){

    return accountInfo;//校验通过,返回账号信息

    }

    return null;

    }

    }

  4. 4

    自定义密码校验器

    /**

    * 自定义shiro密码匹配(密码是在md5散列值的基础上再次进行md5加盐操作,加盐值不保存在数据库,而是放在配置文件中)

    * @author eguid

    *

    */

    public class MyCredentialsMatcher extends CodecSupport implements CredentialsMatcher {

    private static final Logger log = LoggerFactory.getLogger(MyCredentialsMatcher.class);

    protected Object getCredentials(AuthenticationToken token) {

    return token.getCredentials();

    }

    protected Object getCredentials(AuthenticationInfo info) {

    return info.getCredentials();

    }

    @Autowired

    private CommonConfigs commonConfigs;

    /**

    * 验证密码

    *

    * @param tokenCredentials

    * @param accountCredentials

    * @return

    */

    protected boolean equals(Object tokenCredentials, Object accountCredentials) {

    if (log.isDebugEnabled()) {

    log.debug("Performing credentials equality check for tokenCredentials of type ["

    + tokenCredentials.getClass().getName() + " and accountCredentials of type ["

    + accountCredentials.getClass().getName() + "]");

    }

    if (isByteSource(tokenCredentials) && isByteSource(accountCredentials)) {

    if (log.isDebugEnabled()) {

    log.debug("Both credentials arguments can be easily converted to byte arrays.  Performing "

    + "array equals comparison");

    }

    byte[] tokenBytes = toBytes(tokenCredentials);

    byte[] accountBytes = toBytes(accountCredentials);

    return MessageDigest.isEqual(tokenBytes, accountBytes);

    } else {

    return accountCredentials.equals(tokenCredentials);

    }

    }

    public boolean doCredentialsMatch(AuthenticationToken token, AuthenticationInfo info) {

    Object tokenCredentials = getCredentials(token);

    Object accountCredentials = getCredentials(info);

    String account=String.valueOf((char[])tokenCredentials);

    if(commonConfigs.getMd5salt()==null){

    if (log.isDebugEnabled()) {

    log.debug("配置文件中的加盐值为空,无法进行密码匹配,请确认配置文件是否在指定位置或配置指定加盐值");

    }

    return false;

    }

    String saltaccount=MD5Util.getMD5(account, commonConfigs.getMd5salt());

    if (log.isDebugEnabled()) {

    log.debug("加盐后的密码:"+saltaccount);

    }

    return equals(accountCredentials, saltaccount.toCharArray());

    }

    }

  5. 5

    注解使用及模板标签使用

    1、注解使用
    @RequiresPermissions({"user:update:view"})//检查操作权限
    @RequiresPermissions(value={"user:add","user:view"},logical=Logical.OR)//两个操作权限其中一个满足条件即可通过检查
    @RequiresRoles({"admin"})//检查角色
    @RequiresRoles(value={"debug","admin"},logical=Logical.OR)//两个角色其中一个角色满足条件即可

    @RequiresAuthentication//检查是否通过shiro认证
    @RequiresGuest//不需要验证
    @RequiresUser//检查用户是否是当前系统中的用户

    2、标签使用
    使用标签需要先导入shiro的标签库<%@taglib prefix="shiro" uri="http://shiro.apache.org/tags" %>
    (1)显示用户身份信息
    <shiro: principal/>
    默认调用Subject.getPrincipal()获取

    <shiro:principal property="username"/>
    相当于((User)Subject.getPrincipals()).getUsername()

    (2)已登录shiro用户显示

    <shiro:user> 
    欢迎[<shiro:principal/>]登录,<a href="logout">退出</a> 
    <shiro:user>

    (3)匿名用户访问
    <shiro:guest>未经过shiro验证的用户(游客,匿名用户)</shiro:guest>

    (4)已经在shiro登录过的(已登录用户)

    <shiro:authenticated> 
        用户[<shiro:principal/>]已身份验证通过 
    <shiro:authenticated>

    (5)没有在shiro登录过的

    <shiro:notAuthenticated>
        未身份验证(包括记住我)
    <shiro:notAuthenticated>

    (6)检查角色

    <shiro:hasRole name="admin">
        用户[<shiro:principal/>]拥有角色admin<br/>
    <shiro:hasRole>

    检查任意角色(其中一个满足条件即通过,相当于OR)
     <shiro:hasAnyRoles name="admin,user">
        用户[<shiro:principal/>]拥有角色admin或user<br/>
    <shiro:hasAnyRoles>

    不具有角色(反向判断)
     <shiro:lacksRole name="abc">
        用户[<shiro:principal/>]不具有角色abc<br/>
    <shiro:lacksRole>

    (7)操作权限判断

    <shiro:hasPermission name="user:create"> 
        用户[<shiro:principal/>]拥有权限user:create<br/> 
    <shiro:hasPermission>

    不具有操作权限(反向判断)

    <shiro:lacksPermission name="org:create"> 
        用户[<shiro:principal/>]没有权限org:create<br/> 
    <iro:lacksPermission>

    END

Shiro (包含权限满足其中一个就通过的用法)的更多相关文章

  1. Apache Shiro 开源权限框架

    在 Web 项目中应用 Apache Shiro 开源权限框架 Apache Shiro 是功能强大并且容易集成的开源权限框架,它能够完成认证.授权.加密.会话管理等功能.认证和授权为权限控制的核心, ...

  2. springBoot2.0 配置shiro实现权限管理

    一.前言 基于上一篇springBoot2.0 配置 mybatis+mybatisPlus+redis 这一篇加入shiro实现权限管理 二.shiro介绍 2.1 功能特点 Shiro 包含 10 ...

  3. Shiro权限管理框架(三):Shiro中权限过滤器的初始化流程和实现原理

    本篇是Shiro系列第三篇,Shiro中的过滤器初始化流程和实现原理.Shiro基于URL的权限控制是通过Filter实现的,本篇从我们注入的ShiroFilterFactoryBean开始入手,翻看 ...

  4. SpringBoot与Shiro整合权限管理实战

    SpringBoot与Shiro整合权限管理实战 作者 : Stanley 罗昊 [转载请注明出处和署名,谢谢!] *观看本文章需要有一定SpringBoot整合经验* Shiro框架简介 Apach ...

  5. Dubbo学习系列之九(Shiro+JWT权限管理)

    村长让小王给村里各系统来一套SSO方案做整合,隔壁的陈家村流行使用Session+认证中心方法,但小王想尝试点新鲜的,于是想到了JWT方案,那JWT是啥呢?JavaWebToken简称JWT,就是一个 ...

  6. shiro入门笔记之第一个demo创建

    前言 看到这篇文章之前,可能很多小伙伴都没听过shiro,那么shiro是什么呢?shiro是Apache基金会下一个非常有名的开源项目(项目官网: http://shiro.apache.org/ ...

  7. SpringBoot&Shiro实现权限管理

    SpringBoot&Shiro实现权限管理 引言 相信大家前来看这篇文章的时候,是有SpringBoot和Shiro基础的,所以本文只介绍整合的步骤,如果哪里写的不好,恳请大家能指出错误,谢 ...

  8. 【shiro】(5)---基于Shiro的权限管理

    基于Shiro的权限管理项目搭建 前面写了四篇有关权限的文章,算是这篇文章的铺垫了.这篇文章采用 开发环境           JDK1.8          Eclipse          Mav ...

  9. 关于 Shiro 的权限匹配器和过滤器

    项目源码:https://github.com/weimingge14/Shiro-project演示地址:http://liweiblog.duapp.com/Shiro-project/login ...

随机推荐

  1. 笔记-10:处理时间的标准库-time库

    1.time库介绍 主要用来处理时间的标准库. time库提供了系统级精确计时器的计时功能,可以用来分析程序性能,也可让程序暂停运行时间. time库的功能主要分为:时间处理.时间格式化.计时. 2. ...

  2. python — 表的操作(二)

    目录 1.单表查询 2. 多表查询 1.单表查询 单表查询语法: select distinct 字段1,字段2... from 表名 where 条件 group by field having 筛 ...

  3. Fabric中的节点类型

    在Fabric中,尽管所有对等节点/peer都是相同的,但它们可以根据网络的配置方式承担多个角色:(①②是主要的节点类型) ①提交节点: 通道中的每个对等节点都是一个提交节点.它们接收生成的交易区块, ...

  4. SAS学习笔记30 SAS各种常用随机函数

    UNIFORM(seed) 产生(0,1)区域均匀分布随机数,乘同余发生器 RANUNI(seed) 产生(0,1)区域均匀分布随机数,素数模发生器 NORMAL(seed) 产生标准正态分布随机数, ...

  5. Educational Codeforces Round 65 (Rated for Div. 2)

    A:签到. #include<bits/stdc++.h> using namespace std; #define ll long long #define inf 1000000010 ...

  6. MacBook使用HHKB键盘设置

    问题: macbook上使用hhkb的时候,很纠结档位4要不要开,开启4号DIP开关后,虽然会使HHKB键盘上减少一个“◇(Win键)”键,但是会在键盘左侧多出一个“FN”键.多出来的左“FN”键,不 ...

  7. 谷歌浏览器添加插件时显示程序包无效:"CRX_HEADER_INVALID" 解决办法

    今天在添加谷歌插件的时候,却发现谷歌浏览器显示 程序包无效:"CRX_HEADER_INVALID",现整理解决方法如下: 下图是下载好的 .crx 结尾的插件. 将插件的后缀名改 ...

  8. Unity性能优化-DrawCall

    1. DrawCall是啥?其实就是对底层图形程序(比如:OpenGL ES)接口的调用,以在屏幕上画出东西.所以,是谁去调用这些接口呢?CPU.比如有上千个物体,每一个的渲染都需要去调用一次底层接口 ...

  9. JSON和XML格式与对象的序列化及反序列化的辅助类

    下面的代码主要是把对象序列化为JSON格式或XML格式等 using System; using System.Collections.Generic; using System.Globalizat ...

  10. Sublime Text 添加C/C++环境

    轻巧便捷的sublime text 3代码编辑功能非常强大,不过作为一款代码编辑软件,我们要是让它能把我们的c或者c++代码run起来,变成一个轻量级编译器那就更好了!今天来给大家说一下怎么在subl ...