Spring 集成 Shiro

本贴最后更新于 2502 天前,其中的信息可能已经时移世易

web.xml

1. 配置  Shiro 的 shiroFilter.  
2. DelegatingFilterProxy 实际上是 Filter 的一个代理对象. 默认情况下, Spring 会到 IOC 容器中查找和 
<filter-name> 对应的 filter bean. 也可以通过 targetBeanName 的初始化参数来配置 filter bean 的 id.
<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>

applicationContext-shiro.xml

<!--  
1. 配置 SecurityManager!
-->     
<bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">
    <property name="cacheManager" ref="cacheManager"/>
   <!--  多个realm认证策略 -->
   <!--  <property name="authenticator" ref="authenticator"/> -->
    <property name="realm" ref="jdbcRealm"/>
   <!--  多个realm配置 -->
  <!--   <property name="realms">
    	<list>
			<ref bean="jdbcRealm"/>
			<ref bean="secondRealm"/>
		</list>
    </property> -->
    
    <property name="rememberMeManager.cookie.maxAge" value="10"></property>
</bean>

<!--  
2. 配置 CacheManager. 
2.1 需要加入 ehcache 的 jar 包及配置文件. 
-->     
<bean id="cacheManager" class="org.apache.shiro.cache.ehcache.EhCacheManager">
    <property name="cacheManagerConfigFile" value="classpath:ehcache.xml"/> 
</bean>
 <!--  多个realm认证策略 -->
<!-- <bean id="authenticator" 
	class="org.apache.shiro.authc.pam.ModularRealmAuthenticator">
	<property name="authenticationStrategy">
		<bean class="org.apache.shiro.authc.pam.AtLeastOneSuccessfulStrategy"></bean>
	</property>
</bean> -->

<!-- 
	3. 配置 Realm 
	3.1 直接配置实现了 org.apache.shiro.realm.Realm 接口的 bean
-->     
<bean id="jdbcRealm" class="com.atguigu.shiro.realms.ShiroRealm">
	<property name="credentialsMatcher">
		<bean class="org.apache.shiro.authc.credential.HashedCredentialsMatcher">
			<property name="hashAlgorithmName" value="MD5"></property>
			<property name="hashIterations" value="1024"></property>
		</bean>
	</property>
</bean>

<bean id="secondRealm" class="com.atguigu.shiro.realms.SecondRealm">
	<property name="credentialsMatcher">
		<bean class="org.apache.shiro.authc.credential.HashedCredentialsMatcher">
			<property name="hashAlgorithmName" value="SHA1"></property>
			<property name="hashIterations" value="1024"></property>
		</bean>
	</property>
</bean>

<!--  
4. 配置 LifecycleBeanPostProcessor. 可以自定的来调用配置在 Spring IOC 容器中 shiro bean 的生命周期方法. 
-->       
<bean id="lifecycleBeanPostProcessor" class="org.apache.shiro.spring.LifecycleBeanPostProcessor"/>

<!-- Enable Shiro Annotations for Spring-configured beans.  Only run after
     the lifecycleBeanProcessor has run: -->
<!--  
5. 启用 IOC 容器中使用 shiro 的注解. 但必须在配置了 LifecycleBeanPostProcessor 之后才可以使用. 
-->     
<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>

<!--  
6. 配置 ShiroFilter. 
6.1 id 必须和 web.xml 文件中配置的 DelegatingFilterProxy 的 <filter-name> 一致.
                  若不一致, 则会抛出: NoSuchBeanDefinitionException. 因为 Shiro 会来 IOC 容器中查找和 <filter-name> 名字对应的 filter bean.
-->     
<bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">
    <property name="securityManager" ref="securityManager"/>
    <property name="loginUrl" value="/login.jsp"/>
    <property name="successUrl" value="/list.jsp"/>
    <property name="unauthorizedUrl" value="/unauthorized.jsp"/>
     <!-- 动态配置权限从数据库获取 -->
    <property name="filterChainDefinitionMap" ref="filterChainDefinitionMap"></property>
    <!-- 配置权限 -->
    <!--  
    	配置哪些页面需要受保护. 
    	以及访问这些页面需要的权限. 
    	1). anon 可以被匿名访问
    	2). authc 必须认证(即登录)后才可能访问的页面. 
    	3). logout 登出.
    	4). roles 角色过滤器
    -->
    <!--  
    <property name="filterChainDefinitions">
        <value>
            /login.jsp = anon
            /shiro/login = anon
            /shiro/logout = logout
            
            /user.jsp = roles[user]
            /admin.jsp = roles[admin]
            
            # everything else requires authentication:
            /** = authc
        </value>
    </property>
    -->
</bean>
 <!-- 动态配置权限从数据库获取 -->
<!-- 配置一个 bean, 该 bean 实际上是一个 Map. 通过实例工厂方法的方式 -->
<bean id="filterChainDefinitionMap" 
	factory-bean="filterChainDefinitionMapBuilder" factory-method="buildFilterChainDefinitionMap"></bean>

<bean id="filterChainDefinitionMapBuilder"
	class="com.atguigu.shiro.factory.FilterChainDefinitionMapBuilder"></bean>

自定义 realm

public class ShiroRealm extends AuthorizingRealm {

@Override
protected AuthenticationInfo doGetAuthenticationInfo(
		AuthenticationToken token) throws AuthenticationException {
	System.out.println("[FirstRealm] doGetAuthenticationInfo");
	
	//1. 把 AuthenticationToken 转换为 UsernamePasswordToken 
	UsernamePasswordToken upToken = (UsernamePasswordToken) token;
	
	//2. 从 UsernamePasswordToken 中来获取 username
	String username = upToken.getUsername();
	
	//3. 调用数据库的方法, 从数据库中查询 username 对应的用户记录
	System.out.println("从数据库中获取 username: " + username + " 所对应的用户信息.");
	
	//4. 若用户不存在, 则可以抛出 UnknownAccountException 异常
	if("unknown".equals(username)){
		throw new UnknownAccountException("用户不存在!");
	}
	
	//5. 根据用户信息的情况, 决定是否需要抛出其他的 AuthenticationException 异常. 
	if("monster".equals(username)){
		throw new LockedAccountException("用户被锁定");
	}
	
	//6. 根据用户的情况, 来构建 AuthenticationInfo 对象并返回. 通常使用的实现类为: SimpleAuthenticationInfo
	//以下信息是从数据库中获取的.
	//1). principal: 认证的实体信息. 可以是 username, 也可以是数据表对应的用户的实体类对象. 
	Object principal = username;
	//2). credentials: 密码. 
	Object credentials = null; //"fc1709d0a95a6be30bc5926fdb7f22f4";
	if("admin".equals(username)){
		credentials = "038bdaf98f2037b31f1e75b5b4c9b26e";
	}else if("user".equals(username)){
		credentials = "098d2c478e9c11555ce2823231e02ec1";
	}
	
	//3). realmName: 当前 realm 对象的 name. 调用父类的 getName() 方法即可
	String realmName = getName();
	//4). 盐值. 
	ByteSource credentialsSalt = ByteSource.Util.bytes(username);
	
	SimpleAuthenticationInfo info = null; //new SimpleAuthenticationInfo(principal, credentials, realmName);
	info = new SimpleAuthenticationInfo(principal, credentials, credentialsSalt, realmName);
	return info;
}

public static void main(String[] args) {
	String hashAlgorithmName = "MD5";
	Object credentials = "123456";
	Object salt = ByteSource.Util.bytes("user");;
	int hashIterations = 1024;
	
	Object result = new SimpleHash(hashAlgorithmName, credentials, salt, hashIterations);
	System.out.println(result);
}

//授权会被 shiro 回调的方法
@Override
protected AuthorizationInfo doGetAuthorizationInfo(
		PrincipalCollection principals) {
	//1. 从 PrincipalCollection 中来获取登录用户的信息
	Object principal = principals.getPrimaryPrincipal();
	
	//2. 利用登录的用户的信息来用户当前用户的角色或权限(可能需要查询数据库)
	Set<String> roles = new HashSet<>();
	roles.add("user");
	if("admin".equals(principal)){
		roles.add("admin");
	}
	
	//3. 创建 SimpleAuthorizationInfo, 并设置其 reles 属性.
	SimpleAuthorizationInfo info = new SimpleAuthorizationInfo(roles);
	
	//4. 返回 SimpleAuthorizationInfo 对象. 
	return info;
}
}

FilterChainDefinitionMapBuilder.java

public class FilterChainDefinitionMapBuilder {

public LinkedHashMap<String, String> buildFilterChainDefinitionMap(){
	LinkedHashMap<String, String> map = new LinkedHashMap<>();
	//这里可以从数据库读取
	map.put("/login.jsp", "anon");
	map.put("/shiro/login", "anon");
	map.put("/shiro/logout", "logout");
	map.put("/user.jsp", "authc,roles[user]");
	map.put("/admin.jsp", "authc,roles[admin]");
	map.put("/list.jsp", "user");
	
	map.put("/**", "authc");
	
	return map;
}
}

相关帖子

欢迎来到这里!

我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。

注册 关于
请输入回帖内容 ...

推荐标签 标签

  • Bug

    Bug 本意是指臭虫、缺陷、损坏、犯贫、窃听器、小虫等。现在人们把在程序中一些缺陷或问题统称为 bug(漏洞)。

    77 引用 • 1741 回帖
  • 七牛云

    七牛云是国内领先的企业级公有云服务商,致力于打造以数据为核心的场景化 PaaS 服务。围绕富媒体场景,七牛先后推出了对象存储,融合 CDN 加速,数据通用处理,内容反垃圾服务,以及直播云服务等。

    25 引用 • 217 回帖 • 156 关注
  • Ngui

    Ngui 是一个 GUI 的排版显示引擎和跨平台的 GUI 应用程序开发框架,基于
    Node.js / OpenGL。目标是在此基础上开发 GUI 应用程序可拥有开发 WEB 应用般简单与速度同时兼顾 Native 应用程序的性能与体验。

    7 引用 • 9 回帖 • 345 关注
  • Oracle

    Oracle(甲骨文)公司,全称甲骨文股份有限公司(甲骨文软件系统有限公司),是全球最大的企业级软件公司,总部位于美国加利福尼亚州的红木滩。1989 年正式进入中国市场。2013 年,甲骨文已超越 IBM,成为继 Microsoft 后全球第二大软件公司。

    103 引用 • 126 回帖 • 446 关注
  • Hadoop

    Hadoop 是由 Apache 基金会所开发的一个分布式系统基础架构。用户可以在不了解分布式底层细节的情况下,开发分布式程序。充分利用集群的威力进行高速运算和存储。

    82 引用 • 122 回帖 • 620 关注
  • Postman

    Postman 是一款简单好用的 HTTP API 调试工具。

    4 引用 • 3 回帖 • 1 关注
  • 外包

    有空闲时间是接外包好呢还是学习好呢?

    26 引用 • 232 回帖 • 10 关注
  • Mobi.css

    Mobi.css is a lightweight, flexible CSS framework that focus on mobile.

    1 引用 • 6 回帖 • 698 关注
  • NGINX

    NGINX 是一个高性能的 HTTP 和反向代理服务器,也是一个 IMAP/POP3/SMTP 代理服务器。 NGINX 是由 Igor Sysoev 为俄罗斯访问量第二的 Rambler.ru 站点开发的,第一个公开版本 0.1.0 发布于 2004 年 10 月 4 日。

    311 引用 • 546 回帖 • 32 关注
  • JVM

    JVM(Java Virtual Machine)Java 虚拟机是一个微型操作系统,有自己的硬件构架体系,还有相应的指令系统。能够识别 Java 独特的 .class 文件(字节码),能够将这些文件中的信息读取出来,使得 Java 程序只需要生成 Java 虚拟机上的字节码后就能在不同操作系统平台上进行运行。

    180 引用 • 120 回帖
  • Docker

    Docker 是一个开源的应用容器引擎,让开发者可以打包他们的应用以及依赖包到一个可移植的容器中,然后发布到任何流行的操作系统上。容器完全使用沙箱机制,几乎没有性能开销,可以很容易地在机器和数据中心中运行。

    478 引用 • 902 回帖
  • 自由行
    3 关注
  • App

    App(应用程序,Application 的缩写)一般指手机软件。

    90 引用 • 383 回帖
  • VirtualBox

    VirtualBox 是一款开源虚拟机软件,最早由德国 Innotek 公司开发,由 Sun Microsystems 公司出品的软件,使用 Qt 编写,在 Sun 被 Oracle 收购后正式更名成 Oracle VM VirtualBox。

    10 引用 • 2 回帖 • 9 关注
  • Wide

    Wide 是一款基于 Web 的 Go 语言 IDE。通过浏览器就可以进行 Go 开发,并有代码自动完成、查看表达式、编译反馈、Lint、实时结果输出等功能。

    欢迎访问我们运维的实例: https://wide.b3log.org

    30 引用 • 218 回帖 • 603 关注
  • 设计模式

    设计模式(Design pattern)代表了最佳的实践,通常被有经验的面向对象的软件开发人员所采用。设计模式是软件开发人员在软件开发过程中面临的一般问题的解决方案。这些解决方案是众多软件开发人员经过相当长的一段时间的试验和错误总结出来的。

    198 引用 • 120 回帖
  • Bootstrap

    Bootstrap 是 Twitter 推出的一个用于前端开发的开源工具包。它由 Twitter 的设计师 Mark Otto 和 Jacob Thornton 合作开发,是一个 CSS / HTML 框架。

    18 引用 • 33 回帖 • 685 关注
  • WiFiDog

    WiFiDog 是一套开源的无线热点认证管理工具,主要功能包括:位置相关的内容递送;用户认证和授权;集中式网络监控。

    1 引用 • 7 回帖 • 544 关注
  • 博客

    记录并分享人生的经历。

    270 引用 • 2386 回帖
  • CloudFoundry

    Cloud Foundry 是 VMware 推出的业界第一个开源 PaaS 云平台,它支持多种框架、语言、运行时环境、云平台及应用服务,使开发人员能够在几秒钟内进行应用程序的部署和扩展,无需担心任何基础架构的问题。

    5 引用 • 18 回帖 • 153 关注
  • 快应用

    快应用 是基于手机硬件平台的新型应用形态;标准是由主流手机厂商组成的快应用联盟联合制定;快应用标准的诞生将在研发接口、能力接入、开发者服务等层面建设标准平台;以平台化的生态模式对个人开发者和企业开发者全品类开放。

    15 引用 • 127 回帖 • 4 关注
  • Spring

    Spring 是一个开源框架,是于 2003 年兴起的一个轻量级的 Java 开发框架,由 Rod Johnson 在其著作《Expert One-On-One J2EE Development and Design》中阐述的部分理念和原型衍生而来。它是为了解决企业应用开发的复杂性而创建的。框架的主要优势之一就是其分层架构,分层架构允许使用者选择使用哪一个组件,同时为 JavaEE 应用程序开发提供集成的框架。

    941 引用 • 1458 回帖 • 151 关注
  • Elasticsearch

    Elasticsearch 是一个基于 Lucene 的搜索服务器。它提供了一个分布式多用户能力的全文搜索引擎,基于 RESTful 接口。Elasticsearch 是用 Java 开发的,并作为 Apache 许可条款下的开放源码发布,是当前流行的企业级搜索引擎。设计用于云计算中,能够达到实时搜索,稳定,可靠,快速,安装使用方便。

    116 引用 • 99 回帖 • 269 关注
  • 小薇

    小薇是一个用 Java 写的 QQ 聊天机器人 Web 服务,可以用于社群互动。

    由于 Smart QQ 从 2019 年 1 月 1 日起停止服务,所以该项目也已经停止维护了!

    34 引用 • 467 回帖 • 691 关注
  • jsoup

    jsoup 是一款 Java 的 HTML 解析器,可直接解析某个 URL 地址、HTML 文本内容。它提供了一套非常省力的 API,可通过 DOM,CSS 以及类似于 jQuery 的操作方法来取出和操作数据。

    6 引用 • 1 回帖 • 463 关注
  • 互联网

    互联网(Internet),又称网际网络,或音译因特网、英特网。互联网始于 1969 年美国的阿帕网,是网络与网络之间所串连成的庞大网络,这些网络以一组通用的协议相连,形成逻辑上的单一巨大国际网络。

    96 引用 • 330 回帖
  • Facebook

    Facebook 是一个联系朋友的社交工具。大家可以通过它和朋友、同事、同学以及周围的人保持互动交流,分享无限上传的图片,发布链接和视频,更可以增进对朋友的了解。

    4 引用 • 15 回帖 • 455 关注