springmvc简单集成shiro
前言:
	  有天和同事聊天, 谈起权限管理, 他说他有个同事用shiro用的很溜. 正好现在有个管理平台项目, 有权限控制的需求, 因此想借此机会研究一番. 
	  本文主要简单讲解一下对shiro的一些认识, 比较浅显, 同时用一个小的演示demo, 来简单实践一下.
shiro简介:
	  shiro是apache旗下的一个开源安全组件, 它比spring security更容易集成和使用. 
	  官网地址为: Shiro. 
	  其整个架构图如下:
  
	  我觉得核心的一下几个概念: 
	  Subject:主题, 可以理解为用户的超级session, 通过其可以进行认证/授权/权限验证. 
	  SecurityManager:他是 Shiro 的心脏;所有组件都交互都通过SecurityManager进行控制;它管理着所有 Subject、且负责进行认证和授权、及会话、缓存的管理。
	  Realm:它维护了认证/授权的具体实现.
	  至于SessionManager, CacheManager, 这些都属于更进一步的研究, 暂时放放.
通过权限系统设计思想:
	  其实权限系统发展到现在, 由两种主流的做法: 基于角色的权限控制/基于资源的权限控制.
	  数据模型图大致如下:
  
	  通常把资源和权限整合为'新权限', 数据模型图如下:
  
	  注: 该图来源于博文: 从权限到shiro框架.
	  而shiro显然也顺从这种设计思路, 它的权限校验, 主要有role/permission两种方式.
// 1) 校验资源权限
SecurityUtils.getSubject().checkPermission("blog:write");
// 2) 校验角色
SecurityUtils.getSubject().checkRole("admin");
整合实践:
	  整合的springmvc demo参考自官网文档 https://shiro.apache.org/spring.html.
	  添加maven依赖:
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-core</artifactId>
<version>1.4.0</version>
<exclusions>
<exclusion>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-web</artifactId>
<version>1.4.0</version>
</dependency>
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-spring</artifactId>
<version>1.4.0</version>
</dependency>
编写AuthorizingRealm的自定义实现类:
public class DemoRealm extends AuthorizingRealm {
    // *) 校验权限时, 被回调
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
        // 可以添加业务代码
        SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
        // *) 添加role
        info.addRole("admin");
        // *) 添加权限(资源+权限)
        info.addStringPermission("blog:write");
        info.addStringPermission("blog:read");
        return info;
    }
    // *) 认证时被调用
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken)
            throws AuthenticationException {
        // 可以添加业务代码
        SimpleAuthenticationInfo info = new SimpleAuthenticationInfo(
                authenticationToken.getPrincipal(),
                authenticationToken.getCredentials(),
                "simple"
        );
        return info;
    }
}
在web.xml中添加filter
<!-- 添加spring相关的配置文件&属性, 和shiro无关, 但需确保容器的相关bean优于shiroFilter之前创建 -->
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/conf/applicationContext*.xml</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener> <!-- shiro默认的filter -->
<filter>
<description>shiro</description>
<filter-name>shiroFilter</filter-name>
<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
<init-param>
<param-name>targetFilterLifecycle</param-name>
<param-value>false</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>shiroFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
然后在applicationContext.xml添加shiro的相关bean, 这个最简化的情形.
<bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">
<property name="securityManager" ref="securityManager"/>
</bean> <!-- 配置进行授权和认证的 Realm -->
<bean id="myRealm" class="com.springapp.mvc.shiro.DemoRealm" /> <!-- 配置 Shiro 的 SecurityManager Bean. -->
<bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">
<property name="realm" ref="myRealm"/>
</bean> <bean id="lifecycleBeanPostProcessor" class="org.apache.shiro.spring.LifecycleBeanPostProcessor"/>
编写测试用例:
@Controller
@RequestMapping("/")
public class HelloController { @RequestMapping(value="/login", method={RequestMethod.POST, RequestMethod.GET})
@ResponseBody
public String login(
@RequestParam("username") String username,
@RequestParam("password") String password
) {
// 登陆, 既完成shiro的认证流程
Subject subject = SecurityUtils.getSubject();
AuthenticationToken token = new UsernamePasswordToken("username", "password");
subject.login(token);
return "ok";
} @RequestMapping(value = "/test1", method = {RequestMethod.GET, RequestMethod.POST})
@ResponseBody
public String test1() {
// *) 权限存在, 校验会回调授权实现
SecurityUtils.getSubject().checkPermission("blog:write");
return "test1";
} @RequestMapping(value = "/test2", method = {RequestMethod.GET, RequestMethod.POST})
@ResponseBody
public String test2() {
// *) 权限不存在, 校验会回调授权实现
SecurityUtils.getSubject().checkPermission("blog:write1");
return "test2";
} }
测试:
	  就是单纯的测试shiro的认证什么时候进行, 授权又是什么时候被回调. 
	  case 1: 测试认证过程
	  直接rest api调用/login, 观察到自定义的DemoRealm的doGetAuthenticationInfo方法被回调, 此时认证成功.
	  case 2: 不经过认证, 访问受权限保护的资源
	  无论调用/test1, /test2都返回UnauthenticatedException的异常.
	  case 3: 经过认证后, 访问受权限保护的资源
	  访问/test1, pass
	  访问/test2, nopass
	  结果符合预期, 而且观察到DemoRealm的doGetAuthorizationInfo方法被回调, 用户的权限列表默认没缓存(官方推荐ehcache做缓存).
引入注解:
	  除了硬编码, 权限资源的check, 还可以引入注解来实现.
	  在之前的applicationContext.xml中, 添加如下配置, 使得注解生效.
<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>
然后在测试代码中, 添加如下测试接口(注解@RequiresPermissions/@RequiresRoles).
@RequestMapping(value = "/test3", method = {RequestMethod.GET, RequestMethod.POST})
@ResponseBody
@RequiresPermissions("blog:write3")
public String test3() {
	return "test3";
}
@RequestMapping(value = "/test4", method = {RequestMethod.GET, RequestMethod.POST})
@ResponseBody
@RequiresRoles({"admin4"})
public String test4() {
	return "test4";
}
测试的结果都符合预期, 都被完美的拦截下来了.
更进一步:
	  对于面向rest api服务的权限控制需求, 引入注解后, 代码基本上显得非常漂亮了, 简单的配置注解即可完美进行资源访问控制.
	  为了更好的屏蔽异常, 可以引入ControllerAdvice/Interceptor, 用于拦截内部异常, 转换为友好的信息提示. 
	  具体可参看之前写过的文章:
	  1. REST API的异常处理.
	  2. Interceptor机制和实践.
遇到的问题记录:
	  在具体集成springmvc和shiro的过程中, 也遇到了一些坑.
	  1. 遇到shiroFilter实例(ShiroFilterFactoryBean)创建失败, 导致servlet层面的Filter(ShiroFilter)初始化失败.
No bean named 'shiroFilter' is defined
主要原因是要保证ShiroFilter(Serlvet层面)的实例要晚于spring容器的实例初始化(既通过listener, 优先加载applicationContext.xml).
后记:
	  以前后端管理平台是基于MVC的架构构建(即后端也处理路由和页面渲染), 现在流行架构是MVVM(前后端完全分离, 前端做路由和渲染, 后端纯数据服务), 因此对shiro的使用和研究, 不再涉及页面标签这块.
springmvc简单集成shiro的更多相关文章
- springmvc+spring+mybatis+maven项目集成shiro进行用户权限控制【转】
		
项目结构: 1.maven项目的pom中引入shiro所需的jar包依赖关系 ? 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 ...
 - springmvc集成shiro登录失败处理
		
一般的登录流程会有:用户名不存在,密码错误,验证码错误等.. 在集成shiro后,应用程序的外部访问权限以及访问控制交给了shiro来管理. shiro提供了两个主要功能:认证(Authenticat ...
 - 基于spring框架的apache shiro简单集成
		
关于项目的安全保护,我一直想找一个简单配置就能达到目的的方法,自从接触了shiro,这个目标总算达成了,以下结合我使用shiro的经验,谈谈比较轻便地集成该功能. 首先我们先了解一下shiro是什么. ...
 - Spring集成shiro做登陆认证
		
一.背景 其实很早的时候,就在项目中有使用到shiro做登陆认证,直到今天才又想起来这茬,自己抽空搭了一个spring+springmvc+mybatis和shiro进行集成的种子项目,当然里面还有很 ...
 - springmvc学习笔记--ueditor和springmvc的集成
		
前言: 在web开发中, 富文本的编辑器真心很重要. 有电商店铺的打理, 新闻稿/博客文章/论坛帖子的编辑等等, 这种所见即所的编辑方式, 大大方便了非技术人员从事互利网相关的工作. 因为手头有个小项 ...
 - spring springMVC mybatis 集成
		
最近闲来无事,整理了一下spring springMVC mybatis 集成,关于这个话题在园子里已经有很多人写过了,我主要是想提供一个完整的demo,涵盖crud,事物控制等. 整个demo分三个 ...
 - SpringBoot集成Shiro并用MongoDB做Session存储
		
之前项目鉴权一直使用的Shiro,那是在Spring MVC里面使用的比较多,而且都是用XML来配置,用Shiro来做权限控制相对比较简单而且成熟,而且我一直都把Shiro的session放在mong ...
 - Spring boot 入门(四):集成 Shiro 实现登陆认证和权限管理
		
本文是接着上篇博客写的:Spring boot 入门(三):SpringBoot 集成结合 AdminLTE(Freemarker),利用 generate 自动生成代码,利用 DataTable 和 ...
 - 权限管理系统之集成Shiro实现登录、url和页面按钮的访问控制
		
用户权限管理一般是对用户页面.按钮的访问权限管理.Shiro框架是一个强大且易用的Java安全框架,执行身份验证.授权.密码和会话管理,对于Shiro的介绍这里就不多说.本篇博客主要是了解Shiro的 ...
 
随机推荐
- CEF 设置Cookie
			
参考文档:http://magpcss.org/ceforum/apidocs3/projects/(default)/CefCookieManager.html 转载:https://www.cnb ...
 - 《温故而知新》JAVA基础二
			
基本条件语句 switch语句,case匹配后会执行匹配的代码,如果没有break语句,会继续执行后面的语句,直到遇到break和程序结束为止 2.while循环 1. whie(){ do some ...
 - _quick_response
			
在线答题,抢答 `question` 题库 `correctAnswer` 正确答案(A,B,C,D) `answerA` 选项显示 `answerB`选项显示 `answerC` 选项显示 `ans ...
 - sqlserver数据库中sql的使用
			
目录: 1. 分组排序更新 2. 将查询结果插入到新的表中 3. 创建/更新存储过程 4. 创建/更新视图 5. 插入数据 6. 增加表格的列 7. 创建表格 8. 创建索引 9. 递归查询 1. 分 ...
 - 前端UI框架选择区别对比推荐
			
UI选择务必慎重,货比三家. 弱水三千只取一瓢:弱水三千只取一瓢,源起佛经中的一则故事,警醒人们在一生中可能会遇到很多美好的东西,但只要用心好好把握住其中的一样就足够了 老牌构建于jQuery框架之上 ...
 - Linux wc -l 统计文件行数存在的问题
			
1.使用这种方式效率较低,而且不注意可能出现错误 find . -name "*.pc" |xargs wc -l 直接查看 total 不是正确的值. 原因: 这种方式存在一个 ...
 - python模块--re模块
			
常用的正则表达式模式: . 匹配除换行符以外的任意字符 \d 匹配一个数字字符.等价于 [0-9]. \D 匹配一个非数字字符.等价于 [^0-9]. \s 匹配任何空白字符,包括空格.制表符 ...
 - python+unittest+requests+HTMLRunner编写接口自动化测试集
			
问题描述:搭建接口测试框架,执行用例请求多个不同请求方式的接口 实现步骤: ① 创建配置文件config.ini,写入部分公用参数,如接口的基本url.测试报告文件路径.测试数据文件路径等配置项 [D ...
 - Struts2中 Action class not found 问题
			
刚学Struts2时碰到了以下两个问题,都是没有正确配置struts.xml导致的,自己记录一下: 1.浏览器报404:The origin server did not find a current ...
 - 2010-10-08在浏览器中兼容+jQuery3
			
一.实现背景图片铺满(兼容各种浏览器) <script type="text/javascript"> $(document).ready(function() { $ ...