shiro的认证流程

Application Code:应用程序代码,由开发人员负责开发的

Subject:框架提供的接口,代表当前用户对象

SecurityManager:框架提供的接口,代表安全管理器对象

Realm:可以开发人员编写,框架也提供一些,类似于DAO层,用于访问权限数据

引入maven依赖


<!-- https://mvnrepository.com/artifact/org.apache.shiro/shiro-all -->
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-all</artifactId>
<version>1.3.2</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.apache.shiro/shiro-spring -->
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-spring</artifactId>
<version>1.4.0</version>
</dependency>

配置web.xml


<!-- 配置Spring框架提供的用于整合Shiro框架的过滤器 shiro 过滤器一定要保证 要先进入!!
这个过滤器的名字必须与Spring配置文件中的ben配置id相同
--> <filter>
<filter-name>shiroFilter</filter-name>
<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class> </filter> <filter-mapping>
<filter-name>shiroFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>

在Spring配置文件中配置shiro



    <!--shiro 配置方式-->

    <!--注册realm-->
<bean id="myRealm" class="top.wintp.crud.service.MyRealm"/> <!--配置安全管理器-->
<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"> <!--securityManager 注入安全管理器-->
<property name="securityManager" ref="securityManager"/> <!--注入相关页面的访问URL--> <property name="loginUrl" value="/user/login.do"/>
<!--<property name="successUrl"/>-->
<property name="unauthorizedUrl" value="/user/unAuth.do"/> <!--
注入URL拦截规则
-->
<property name="filterChainDefinitions">
<value>
/static/** = anon
/user/login.do=anon
/user/loginUser.do=anon
/emp/findAll.do=perms["admin"]
/** = authc
</value>
</property> </bean>

MyRealm

package top.wintp.crud.service;

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.realm.AuthorizingRealm;
import org.apache.shiro.realm.Realm;
import org.apache.shiro.subject.PrincipalCollection;
import org.springframework.beans.factory.annotation.Autowired; import java.util.List; import top.wintp.crud.dao.TUserMapper;
import top.wintp.crud.entity.TUser;
import top.wintp.crud.entity.TUserExample; /**
* 类描述:
* <p>
* 作者: pyfysf
* <p>
* qq: 337081267
* <p>
* CSDN: http://blog.csdn.net/pyfysf
* <p>
* 个人博客: http://wintp.top
* <p>
* 邮箱: pyfysf@163.com
* <p>
* 时间:2018/8/22
*/
public class MyRealm extends AuthorizingRealm { @Autowired
private TUserMapper mTUserMapper; @Override
protected AuthorizationInfo
doGetAuthorizationInfo(PrincipalCollection principalCollection) { System.out.println("自定义realm授权方法"); @Override
protected AuthorizationInfo
doGetAuthorizationInfo(PrincipalCollection principalCollection) { System.out.println("自定义realm授权方法");
TUser user = (TUser) principalCollection.getPrimaryPrincipal(); System.out.println(user.getUsername());
System.out.println(user.getPassword()); SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo(); authorizationInfo.addStringPermission("admin"); //授权
return authorizationInfo;
} @Override
protected AuthenticationInfo
doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
System.out.println("自定义realm认证方法"); UsernamePasswordToken token = (UsernamePasswordToken) authenticationToken; TUserExample tUserExample = new TUserExample();
tUserExample.createCriteria().andUsernameEqualTo(token.getUsername());
List<TUser> tUsers = mTUserMapper.selectByExample(tUserExample); if (tUsers != null && tUsers.size() > 0) { TUser tUser = tUsers.get(0); //简单认证信息对象
AuthenticationInfo authenticationInfo = new SimpleAuthenticationInfo(tUser, tUser.getPassword(), this.getName()); //认证
return authenticationInfo;
} else {
return null;
} }
}

修改用户登录的方法

@Service
public class UserService { public boolean loginUser(TUser user) { String username = user.getUsername(); //shiro执行过程 获取当前用户--subject -->然后获取securityManager(安全管理器)(login 登录)
// 然后调用realm //获取当前用户对象 -- 未认证
Subject subject = SecurityUtils.getSubject(); UsernamePasswordToken token
= new UsernamePasswordToken(user.getUsername(), user.getPassword()); try {
subject.login(token); TUser resultUer = (TUser) subject.getPrincipal(); System.out.println("登录成功"); return true; } catch (Exception e) {
//代表认证失败
e.printStackTrace(); return false;
}
}
}

常用过滤器配置简称

注解式编程

首先需要在Spring的配置文件中开启Shiro的注解支持:在applicationContext.xml中加入下面代码:


<!--开启shiro 框架的注解支持-->
<bean id="advisorAutoProxyCreator"
class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator">
<!--默认开启CGLIB代理-->
<property name="proxyTargetClass" value="true"/>
</bean> <!--配置切面 用于创建代理对象-->
<bean class="org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor"/>

有了上面的配置,我们就可以在我们的代码中使用Shiro的注解进行权限控制了:


@RequestMapping("/findAll")
@RequiresPermissions("emp-check")
public String findAll(Model model, @RequestParam(value = "pageNum", defaultValue = "1")
Integer pageNum) { logger.info("请求开始>>>>>"); //书写分页逻辑--在这里进行分页声明之后,后面紧跟的查询就是一个分页目标
//第二个参数是指定每次查询几条数据
PageHelper.startPage(pageNum, 5); //调用Service里面的方法进行使用
List<Employee> allEmployees = mEmployeeService.findAll();
//使用PageInfo来包装返回的数据--可以更好的管理分页逻辑 //第二个参数是页面上最多显示几个页数,比如限制只显示5个那么就为1,2,3,4,5
//2,3,4,5,6||||3,4,5,6,7
PageInfo<Employee> employeePageInfo = new PageInfo<Employee>(allEmployees, 5); logger.info("数据为:" + employeePageInfo); logger.info("请求结束>>>>>"); //存储数据,跳转界面
model.addAttribute("employeePageInfo", employeePageInfo);
return "list";
}

中途遇到的问题

配置注解之后,没有起到任何作用。

可能一:在你的spring的配置文件中忽略扫描Controller注解,然而你在Controller中使用了@RequiresPermissions,那么我们需要把上面注解支持的代码配置到Spring-mvc.xml文件中。


<!--扫描所有包-->
<context:component-scan base-package="top.wintp.crud">
<!--除了控制器 都进行注解扫描-->
<context:exclude-filter type="annotation"
expression="org.springframework.stereotype.Controller"/> </context:component-scan>

如果有上面的配置,那么spring将不会扫描到Controller注解

可能二:在你的spring-mvc中仅仅只是扫描到了Controller注解,然而你在service层或者dao层用到了@RequiresPermissions,那么我们需要把上面注解支持的代码配置到applicationContext.xml文件中。

  <context:component-scan base-package="top.wintp.crud" use-default-filters="false">
<!--只扫描控制器即可-->
<context:include-filter type="annotation"
expression="org.springframework.stereotype.Controller"/> </context:component-scan>

建议:在Spring的主配置文件中和Springmvc的配置文件中都加入对shiro注解的支持。特别注意:如果两个配置文件中都配置了,注意其id不能相同

在jsp中使用shiro提供的标签库

一、引入标签库
<%@ taglib prefix="shiro" uri="http://shiro.apache.org/tags" %>
二、使用合适的标签在合适的位置进行使用

例如:

<shiro:hasPermission name="admin">

    <button class="btn btn-primary" id="btn_add_emp">新增</button>
<button class="btn btn-danger btn_all_del">删除</button>
</shiro:hasPermission>

上述代码为,当当前用户具有admin的权限时,新增和删除按钮才会显示

Spring集成Shiro使用小结的更多相关文章

  1. Spring集成shiro做登陆认证

    一.背景 其实很早的时候,就在项目中有使用到shiro做登陆认证,直到今天才又想起来这茬,自己抽空搭了一个spring+springmvc+mybatis和shiro进行集成的种子项目,当然里面还有很 ...

  2. spring集成shiro报错解决(no bean named 'shiroFilter' is defined)

    引言: 本人在使用spring集成shiro是总是报“no bean named 'shiroFilter' is defined”,网上的所有方式挨个试了一遍,又检查了一遍, 还是没有解决,最后,抱 ...

  3. shiro实战系列(十五)之Spring集成Shiro

    Shiro 的 JavaBean 兼容性使得它非常适合通过 Spring XML 或其他基于 Spring 的配置机制.Shiro 应用程序需要一个具 有单例 SecurityManager 实例的应 ...

  4. spring 集成shiro 之 自定义过滤器

    在web.xml中加入 <!-- 过期时间配置 --> <session-config><session-timeout>3</session-timeout ...

  5. Shiro学习总结(10)——Spring集成Shiro

    1.引入Shiro的Maven依赖 [html] view plain copy <!-- Spring 整合Shiro需要的依赖 --> <dependency> <g ...

  6. spring集成shiro登陆流程(下)

    首先声明入门看的张开涛大神的<跟我学shiro> 示例:https://github.com/zhangkaitao/shiro-example 博客:http://jinnianshil ...

  7. spring集成shiro登陆流程(上)

    上一篇已经分析了shiro的入口filter是SpringShiroFilter, 那么它的doFilter在哪儿呢? 我们看到它的直接父类AbstractShrioFilter继承了OncePerR ...

  8. Spring集成shiro+nginx 实现访问记录

    最近公司的网站需要添加用户访问记录功能,由于使用了nginx请求转发直接通过HttpServletRequest无法获取用户真实Ip 关于nginx获取真实IP的资料  https://blog.cs ...

  9. spring集成shiro,事务失效问题 not eligible for auto-proxying

    BeanPostProcessor bean实例化顺序有关,@Configuration会最先实例化,也就是在spring启动完成之前. 导致Configuration中使用的注入,没能在spring ...

随机推荐

  1. 程序员该如何过好他的整个职业生涯?(最重要的是你得一直往前走。拐点不是你的工资。想起很久前有个人说我“逻辑性”比较强)good

    作者|池建强 编辑|小智   戳阅读原文,获得短信提醒,不错过下次InfoQ大咖说直播! 1 写在前面 加入极客邦的第一天就被拉到了「大咖说」的现场,这也是我始料未及的事情.从锤子科技正式离职之后,我 ...

  2. 以太坊(ethereum)开发DApp应用的入门区块链技术教程

    概述 对初学者,首先要了解以太坊开发相关的基本概念.   学习以太坊开发的一般前序知识要求,最好对以下技术已经有一些基本了解: 一种面向对象的开发语言,例如:Python,Ruby,Java... 前 ...

  3. MFC 中 Tooltip 实现的几种方式

    方法一:利用CWnd本身自身支持的tooptip来实现,这种方法适用给控件增加tooltip,非常方便和简单方法如下:1.在窗口中增加消息映射ON_NOTIFY_EX(TTN_NEEDTEXT, 0, ...

  4. Boyer-Moore字符串查找算法的实现

    前段时间在园子里看到一篇讲Boyer-Moore算法原理的文章http://kb.cnblogs.com/page/176945/,写的很详细,于是在这里自己写个C语言的实现,权当是练手吧. 基本思路 ...

  5. 使用Arcgis Api for Javascript 调用 本地Portal发布的WebMap

    1.环境搭建 安装Arcgis Portal 10.4,Server 10.4,DataStore ,WebAdaptor for IIS,搭建arcgis api for javascript 4. ...

  6. Java 函数传入参数后,究竟发生了什么?java函数传参数原理解析

    JAVA函数在传入参数A时,会在函数作用周期内生成一个与参数相同类型的局部变量B. B与A指向同一块内存区域,并且具有相同的名字如param. 在函数内所有对param的操作都是对B的操作.对B进行赋 ...

  7. hive表批处理

    对hive中的表进行批量处理,如下是一个简单的脚本 #给定一个hive数据库名,生成它的所有表的create SQL语句,并导出到文件 create_fun(){ hive -e } #显示一个表中所 ...

  8. springboot读取本地项目文件

    在读取springBoot+gradle构建的项目时,如果使用传统的FileInputStream读取文件流或者ResourceUtils工具类的方式 File file= ResourceUtils ...

  9. spring 5.x 系列第1篇 —— springmvc基础 (xml配置方式)

    文章目录 一.搭建hello spring工程 1.1 项目搭建 1.2 相关配置讲解 二.配置自定义拦截器 三.全局异常处理 四.参数绑定 4.1 参数绑定 4.2 关于日期格式转换的三种方法 五. ...

  10. docker search/pull 报错

    docker报错 Get https://registry-1.docker.io/v2/: x509: certificate has expired or is not yet valid 这种错 ...