细说shiro之四:在web应用中使用shiro
1. 下载
在Maven项目中的依赖配置如下:
<!-- shiro配置 -->
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-core</artifactId>
<version>1.3.2</version>
</dependency>
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-web</artifactId>
<version>1.3.2</version>
</dependency> <!-- 配置日志组件 -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.7.25</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-jcl</artifactId>
<version>1.7.25</version>
</dependency>
<dependency>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
<version>1.2</version>
</dependency>
特别地!Shiro使用了日志框架slf4j,因此需要对应配置指定的日志实现组件,如:log4j,logback等。
而且,由于shiro-web组件使用apache commons logging组件中的工具类,所以在项目中必须添加commongs logging组件。
否则,程序启动时将会报错:
java.lang.NoClassDefFoundError: org/apache/commons/logging/LogFactory
at org.apache.commons.beanutils.ConvertUtilsBean.<init>(ConvertUtilsBean.java:157)
at org.apache.commons.beanutils.BeanUtilsBean.<init>(BeanUtilsBean.java:117)
at org.apache.commons.beanutils.BeanUtilsBean$1.initialValue(BeanUtilsBean.java:68)
at org.apache.commons.beanutils.ContextClassLoaderLocal.get(ContextClassLoaderLocal.java:153)
at org.apache.commons.beanutils.BeanUtilsBean.getInstance(BeanUtilsBean.java:80)
at org.apache.commons.beanutils.PropertyUtilsBean.getInstance(PropertyUtilsBean.java:114)
at org.apache.commons.beanutils.PropertyUtils.getPropertyDescriptor(PropertyUtils.java:460)
at org.apache.shiro.config.ReflectionBuilder.isTypedProperty(ReflectionBuilder.java:409)
at org.apache.shiro.config.ReflectionBuilder.applyProperty(ReflectionBuilder.java:702)
at org.apache.shiro.config.ReflectionBuilder.applySingleProperty(ReflectionBuilder.java:364)
at org.apache.shiro.config.ReflectionBuilder.applyProperty(ReflectionBuilder.java:325)
at org.apache.shiro.config.ReflectionBuilder$AssignmentStatement.doExecute(ReflectionBuilder.java:955)
at org.apache.shiro.config.ReflectionBuilder$Statement.execute(ReflectionBuilder.java:887)
at org.apache.shiro.config.ReflectionBuilder$BeanConfigurationProcessor.execute(ReflectionBuilder.java:765)
at org.apache.shiro.config.ReflectionBuilder.buildObjects(ReflectionBuilder.java:260)
at org.apache.shiro.config.IniSecurityManagerFactory.buildInstances(IniSecurityManagerFactory.java:167)
at org.apache.shiro.config.IniSecurityManagerFactory.createSecurityManager(IniSecurityManagerFactory.java:130)
at org.apache.shiro.config.IniSecurityManagerFactory.createSecurityManager(IniSecurityManagerFactory.java:108)
at org.apache.shiro.config.IniSecurityManagerFactory.createInstance(IniSecurityManagerFactory.java:94)
at org.apache.shiro.config.IniSecurityManagerFactory.createInstance(IniSecurityManagerFactory.java:46)
at org.apache.shiro.config.IniFactorySupport.createInstance(IniFactorySupport.java:123)
at org.apache.shiro.util.AbstractFactory.getInstance(AbstractFactory.java:47)
at org.apache.shiro.web.env.IniWebEnvironment.createWebSecurityManager(IniWebEnvironment.java:203)
....
2.集成Shiro
在Java Web应用中使用Shiro,需要特别的集成方式,不再像在非Web环境的独立应用中使用Shiro那么简单(只需要下载Shiro并添加到项目即可)。
通常,在Java Web应用中集成框架都是从配置web.xml开始的,集成Shiro也不例外。
web.xml:
<listener>
<listener-class>org.apache.shiro.web.env.EnvironmentLoaderListener</listener-class>
</listener> <filter>
<filter-name>ShiroFilter</filter-name>
<filter-class>org.apache.shiro.web.servlet.ShiroFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>ShiroFilter</filter-name>
<url-pattern>/*</url-pattern>
<dispatcher>REQUEST</dispatcher>
<dispatcher>FORWARD</dispatcher>
<dispatcher>INCLUDE</dispatcher>
<dispatcher>ERROR</dispatcher>
</filter-mapping>
通常,在Java Web应用中集成第三方框架,都是从Filter开始。Shiro也是如此,即需要将所有请求都经过Shiro指定的Filter进行拦截,这样才能完成用户对指定资源访问的授权验证。
特别地,从Shiro 1.2+版本之后,在Java Web应用中集成Shiro非常简单,甚至都不需要明确指定shiro配置文件的路径,而是直接在web.xml中添加org.apache.shiro.web.env.EnvironmentLoaderListener即可(只需要保证在${webapp}/WEB-INF/目录下存在文件shiro.ini)。
3. 数据源配置
在Shiro中,Realm定义了访问数据的方式,用来连接不同的数据源,如:LDAP,关系数据库,配置文件等等。
Realm类图:
也就是说,可以根据实际需求及应用的权限管理复杂度灵活选择指定数据源。
在此,以org.apache.shiro.realm.text.IniRealm为例,具体配置如下:
shiro.ini:
[main]
# 自定义过滤器
sessionFilter = org.chench.test.shiroweb.filter.SessionFilter
authc.loginUrl = /index
ssl.enabled = false # -----------------------------------------------------------------------------
# Users and their (optional) assigned roles
# username = password, role1, role2, ..., roleN
# -----------------------------------------------------------------------------
[users]
root = secret, admin
guest = guest, guest
presidentskroob = 12345, president
darkhelmet = ludicrousspeed, darklord, schwartz
lonestarr = vespa, goodguy, schwartz # -----------------------------------------------------------------------------
# Roles with assigned permissions
# roleName = perm1, perm2, ..., permN
# -----------------------------------------------------------------------------
[roles]
admin = *
schwartz = lightsaber:*
goodguy = winnebago:drive:eagle5 # -----------------------------------------------------------------------------
# The format of each line in the urls section is as follows:
# _URL_Ant_Path_Expression_ = _Path_Specific_Filter_Chain_
# -----------------------------------------------------------------------------
[urls]
/index = anon, sessionFilter
/user/signin = anon
/user/login = anon
/user/** = authc
/home/** = authc
#/admin/** = authc, roles[administrator]
#/rest/** = authc, rest
#/remoting/rpc/** = authc, perms["remote:invoke"]
4. 认证
在Shiro中,认证即执行用户登录,读取指定Realm连接的数据源,以验证用户身份的有效性与合法性。
关于Shiro在Web应用中的认证流程,与Shiro在非Web环境的独立应用中的认证流程一样,都需要执行用户登录,即:
Subject currentUser = SecurityUtils.getSubject();
if(!currentUser.isAuthenticated()) {
UsernamePasswordToken token = new UsernamePasswordToken(name, password);
try {
currentUser.login(token);
} catch (UnknownAccountException e) {
exception = e;
logger.error(String.format("user not found: %s", name), e);
} catch(IncorrectCredentialsException e) {
exception = e;
logger.error(String.format("user: %s pwd: %s error", name, password), e);
} catch (ConcurrentAccessException e) {
exception = e;
logger.error(String.format("user has been authenticated: %s", name), e);
} catch (AuthenticationException e) {
exception = e;
logger.error(String.format("account except: %s", name), e);
}
}
唯一的区别就是,在Java Web环境中,用户名和密码参数是通过前端页面进行传递。
5. 授权
需要再三强调!!!Shiro作为权限框架,仅仅只能控制对资源的操作权限,并不能完成对数据权限的业务需求。
而对于Java Web环境下Shiro授权,包含个方面的含义。
其一,对于前端来说,用户只能看到他对应访问权限的元素。
其二,当用户执行指定操作(即:访问某个uri资源)时,需要验证用户是否具备对应权限。
对于第一点,在Java Web环境下,通过Shiro提供的JSP标签实现。
<shiro:hasRole name="admin">
<a>用户管理</a>
</shiro:hasRole>
<shiro:hasPermission name="winnebago:drive:eagle5">
<a>操作审计</a>
</shiro:hasPermission>
必须在jsp页面中引入shiro标签库:
<%@ taglib prefix="shiro" uri="http://shiro.apache.org/tags" %>
对于第二点,与在非Java Web环境下一样,需要在后端调用API进行权限(或者角色)检验。如果在Spring框架中集成Shiro,还可以直接通过Java注解方式实现。
api调用:
String roleAdmin = "admin";
Subject currentUser = SecurityUtils.getSubject();
if(!currentUser.hasRole(roleAdmin)) {
//todo something
}
6. 完整示例
详见:https://git.oschina.net/cchanghui/test-shiroweb.git
细说shiro之四:在web应用中使用shiro的更多相关文章
- 在web项目中使用shiro(认证、授权)
一.在web项目中实现认证 第一步,在web项目中导入shiro依赖的包 第二步,在web.xml中声明shiro拦截权限的过滤器 <filter> <filter-name> ...
- SpringBoot系列: SpringBoot Web项目中使用Shiro 之二
==================================Shiro 的加深理解:==================================1. Shiro 和 Spring 系组 ...
- SpringBoot系列: SpringBoot Web项目中使用Shiro
注意点有:1. 不要启用 spring-boot-devtools, 如果启用 devtools 后, 不管是热启动还是手工重启, devtools总是试图重新恢复之前的session数据, 很有可能 ...
- 在web项目中使用shiro(记住我功能)
第一步,添加“记住我”复选框,rememberMe要设置参数 第二步,配置shiro的主配置文件 注意 rememberMeCookie对应的bean中要声明 <constructor-arg ...
- 细说shiro之五:在spring框架中集成shiro
官网:https://shiro.apache.org/ 1. 下载在Maven项目中的依赖配置如下: <!-- shiro配置 --> <dependency> <gr ...
- Apache Shiro:【1】Shiro基础及Web集成
Apache Shiro:[1]Shiro基础及Web集成 Apache Shiro是什么 Apache Shiro是一个强大且易于使用的Java安全框架,提供了认证.授权.加密.会话管理,与spri ...
- Web登录验证之 Shiro
1.需要用到的shiro相关包 <!-- shiro begin --> <dependency> <groupId>org.apache.shiro</gr ...
- Shiro【授权、整合Spirng、Shiro过滤器】
前言 本文主要讲解的知识点有以下: Shiro授权的方式简单介绍 与Spring整合 初始Shiro过滤器 一.Shiro授权 上一篇我们已经讲解了Shiro的认证相关的知识了,现在我们来弄Shiro ...
- shiro系列三、ssm框架整合shiro实现权限控制
shiro权限框架是一个非常优秀的框架,前面的几篇文章对shiro进行了非常详细的介绍和原理分析,那么接下来让我们开始在web项目中使用它(javase也能用shiro): 一.数据库表结构设计 二. ...
随机推荐
- Linux iptables设置
先举例子说明,若服务器网卡: eth0 10.10.0.100 eth0:0 10.10.0.200 eth0:1 10.10.0.201 eth0:2 10.10.0.202 只允许10.10.0. ...
- 【BZOJ3174】[TJOI2013]拯救小矮人(贪心,动态规划)
[BZOJ3174][TJOI2013]拯救小矮人(贪心,动态规划) 题面 BZOJ 洛谷 题解 我们定义一个小矮人的\(A_i+B_i\)为它的逃跑能力. 我们发现,如果有两个小矮人\(x,y\), ...
- python中,下级模块引用上级模块:SystemError: Parent module '' not loaded, cannot perform relative import
当在下级中引用上级时,使用相对导包会出错,SystemError: Parent module '' not loaded, cannot perform relative import 运行test ...
- [NOI2010]航空管制(拓扑排序+贪心)
题目描述 世博期间,上海的航空客运量大大超过了平时,随之而来的航空管制也频频发生.最近,小X就因为航空管制,连续两次在机场被延误超过了两小时.对此,小X表示很不满意. 在这次来烟台的路上,小X不幸又一 ...
- 【php】php实现数组反转
php里面有个函数可以反转数组,工作中也经常用到,非常方便.今天来自己实现这样的功能. $arr = [2,5,6,1,8,16,12]; function reverse($arr){ $left ...
- 第十七篇-使用RadioGroup实现单项选择
上效果图 首先进行控件布局,一个textview,6个radiobutton, main_activity.xml <?xml version="1.0" encoding= ...
- c++ stl sort
两者相等时,必须为false. 满足拟序. 群里大佬666.
- 斯坦福大学公开课机器学习:advice for applying machine learning | learning curves (改进学习算法:高偏差和高方差与学习曲线的关系)
绘制学习曲线非常有用,比如你想检查你的学习算法,运行是否正常.或者你希望改进算法的表现或效果.那么学习曲线就是一种很好的工具.学习曲线可以判断某一个学习算法,是偏差.方差问题,或是二者皆有. 为了绘制 ...
- go的net/http用法
http包提供了HTTP客户端和服务端的实现 一:http客户端的几种方法 1. func (c *Client) Get(url string) (resp *Response, err error ...
- linux driver ------ platform模型,驱动开发分析
一.platform总线.设备与驱动 在Linux 2.6 的设备驱动模型中,关心总线.设备和驱动3个实体,总线将设备和驱动绑定.在系统每注册一个设备的时候,会寻找与之匹配的驱动:相反的,在系统每注册 ...
