Apache Shiro (最初称为JSecurity)是Java安全框架。 它被接受并于2010年成为Apache顶级项目。它的目标是功能强大且易于使用。

该项目正在积极开发中,用户和开发人员的邮件列表均处于活动状态。 最重要的区域记录在其网页上。 但是,它在文档上有很多空白。 仅从文档中就不可能学会使用大多数Shiro功能。 幸运的是,该代码的注释很好,在我尝试过的地方也很容易阅读。

Shiro的主要功能是:

  • 验证,
  • 授权,
  • 密码学
  • 会话管理。

在本文中,我们尝试演示Shiro的各种功能。 我们从简单的不安全Web应用程序开始,然后向其中添加安全功能。 所有代码均在Github上的SimpleShiroSecuredApplication项目中可用。
不安全的应用程序

不安全的应用程序代码位于unsecured_application分支中。 应用程序代表一个虚构公司的内部系统。 该公司有四个部门:

  • 管理员,
  • 修理工
  • 科学家们,
  • 销售。

每个部门都有自己的页面。 每个页面都包含用户用来完成其工作的按钮。 当用户按下按钮时,工作就完成了。 例如,任何维修人员都可以转到维修人员页面,然后按“维修冰箱”按钮。 该按钮将修复冰箱并显示成功消息。

每个用户都有自己的帐户页面。 帐户页面包含用户的私人数据。 由于不安全的应用程序尚无用户,因此帐户页面不执行任何操作。 此外,还有一个页面包含所有应用程序功能。 任何人都可以做的所有事情都可以在此页面上完成。

任何人都可以做任何工作并查看所有页面 。示例应用程序在测试类RunWaitTest中运行。 以这种方式使用单元测试不是最佳实践,但现在并不重要。 如果您运行该类,则该应用程序将位于http:// localhost:9180 / simpleshirosecuredapplication / url中。

添加身份验证

首先,我们必须验证用户的身份。 最简单,最标准的身份验证是通过用户名和密码来完成的。 用户填写其用户名和密码,然后系统验证提供的值是否与某个用户帐户匹配。

对于最简单的应用程序,将用户名和密码存储在纯文本文件中就足够了。 在更现实的情况下,用户名和密码存储在持久性存储中,或者通过其他系统(例如ldap或活动目录)进行验证。 Shiro支持所有提到的身份验证方法。 如果开箱即用的身份验证功能不足,则可以使用自己的验证实现来扩展框架。

在本章中,我们将基于用户名和密码的身份验证添加到应用程序中。 用户名和密码存储在静态纯文本Shiro ini文件中。

新要求:可以登录和注销用户。 该应用程序仅可用于登录用户。 成功登录会将用户重定向到他自己的帐户页面。 所有登录用户仍然可以访问所有应用程序功能和页面。

所需步骤:

  • 添加Apache Shiro,
  • 创建登录页面,
  • 配置用户和密码,
  • 创建注销页面。

添加Apache Shiro

Shiro通过Servlet过滤器集成到Web应用程序中。 过滤器在servlet之前拦截请求和响应,并执行所有必要的任务(例如,标识当前登录的用户,将登录的用户附加到当前线程等)。 默认的Shiro筛选器提供基本的安全功能,例如:

  • 强制用户登录,
  • 执行ssl,
  • 检查页面访问权限。

如果您想了解有关默认Shiro过滤器的更多信息,那么最好的起点是DefaultFilter枚举。 它列出了所有默认可用的Shiro过滤器。 如果这些不足以满足您的需求,则可以创建自定义的。

我们将使用高度可配置的IniShiroFilter 。 它从ini文件读取Shiro配置并初始化安全框架。 它不执行任何安全检查。 权限检查,用户登录,协议检查等都委托给默认或自定义过滤器。 IniShiroFilter仅初始化它们。

文档和javadoc中都介绍了Ini配置。 Ini文件配置包含四个部分:

  • [main]部分包含Shiro初始化。 过滤器和自定义对象在此处配置。
  • [用户]部分定义用户,密码和角色。
  • [角色]部分将角色与权限相关联。
  • [urls]部分指定对应用程序页面(url)的访问权限。 通过将默认或自定义过滤器绑定到url来完成此操作。

将Apache Shiro依赖项添加到pom.xml:

<properties><shiro.version>1.1.0</shiro.version>
</properties>
<dependencies><dependency><groupid>org.apache.shiro</groupid><artifactid>shiro-core</artifactid><version>${shiro.version}</version></dependency><dependency><groupid>org.apache.shiro</groupid><artifactid>shiro-web</artifactid><version>${shiro.version}</version></dependency>
</dependencies>

创建Shiro.ini文件并将其放在类路径中。 将web.xml配置为在每个请求之前调用IniShiroFilter:

<filter><filter-name>ShiroFilter</filter-name><filter-class>org.apache.shiro.web.servlet.IniShiroFilter</filter-class><init-param><param-name>configPath</param-name><param-value>classpath:Shiro.ini</param-value></init-param>
</filter><filter-mapping><filter-name>ShiroFilter</filter-name><url-pattern>/*</url-pattern>
</filter-mapping>

创建登录页面

登录页面是带有提交按钮,用户名和密码字段的简单html页面。 登录功能默认为Shiro authc过滤器处理。 Authc过滤器仅允许登录用户访问url。 如果用户未登录,过滤器会将其重定向到登录页面。

登录页面上的表单名称必须为“ loginform”,其提交方法必须为“ post”。 创建login.jsp页面:

<form name="loginform" action="" method="post">
<table align="left" border="0" cellspacing="0" cellpadding="3"><tr><td>Username:</td><td><input type="text" name="user" maxlength="30"></td></tr><tr><td>Password:</td><td><input type="password" name="pass" maxlength="30"></td></tr><tr><td colspan="2" align="left"><input type="checkbox" name="remember"><font size="2">Remember Me</font></td></tr><tr><td colspan="2" align="right"><input type="submit" name="submit" value="Login"></td></tr>
</table>
</form>

为所有应用程序页面启用authc过滤器:

[main]
# specify login page
authc.loginUrl = /simpleshirosecuredapplication/account/login.jsp# name of request parameter with username; if not present filter assumes 'username'
authc.usernameParam = user
# name of request parameter with password; if not present filter assumes 'password'
authc.passwordParam = pass
# does the user wish to be remembered?; if not present filter assumes 'rememberMe'
authc.rememberMeParam = remember# redirect after successful login
authc.successUrl  = /simpleshirosecuredapplication/account/personalaccountpage.jsp[urls]
# enable authc filter for all application pages
/simpleshirosecuredapplication/**=authc

更新: Shiro自动执行上下文相关的路径匹配。 由于SimpleShiroSecuredApplication没有设置上下文路径,因此Shiro.ini中的完整路径是必需的。 但是,如果应用程序上下文路径为/ simpleshirosecuredapplication,则路径可能是相对的:例如,简单的/ ** = authc或/account/personalaccountpage.jsp。

由于通过网络发送未加密的用户名和密码是不安全的,因此我们应强制使用ssl登录。 SSL过滤器正是这样做的。 它具有一个可选参数:ssl端口号。 如果省略port参数,它将使用默认的ssl端口443。

在Shiro中配置ssl之前,我们必须在Web服务器上启用它。 具体操作取决于Web服务器。 我们展示了如何在Jetty中启用它。 首先,使用自签名证书创建密钥库:

keytool -genkey -keyalg RSA -alias jetty -keystore keystore -storepass secret -validity 360 -keysize 2048

回答所有问题,最后按Enter键,以便密钥库密码和密钥密码相同。

其次,将密钥库添加到项目中,并将Jetty配置为使用ssl。 Java代码在AbstractContainerTest类中可用。

现在,可以在Shiro.ini中配置ssl过滤器:

[urls]
# force ssl for login page
/simpleshirosecuredapplication/account/login.jsp=ssl[8443],authc
# enable authc filter for the all application pages; as Shiro reads urls from up to down, must be last
/simpleshirosecuredapplication/**=authc

配置用户和密码

现在,SimpleShiroSecuredApplication仅适用于登录用户。 现在,我们需要添加一些用户,以便人们可以登录。配置在Shiro.ini文件的[用户]部分中完成。 部分条目的格式为:

username = password, roleName1, roleName2, ..., roleNameN

以下部分创建七个用户,所有用户都具有相同的密码“ heslo”:

[users]
administrator=heslo,Administrator
friendlyrepairmen=heslo,repairmen
unfriendlyrepairmen=heslo,repairmen
mathematician=heslo,scientist
physicien=heslo,scientist
productsales=heslo,sales
servicessales=heslo,sales

现在可以登录到应用程序。 但是,如果用户犯了错误,则不会显示任何合理的错误消息。 此外,密码存储在纯文本文件中。

错误处理

如果用户在登录时出错,则Shiro会将其重定向回登录页面。 该页面看起来与以前完全相同,这可能会使用户感到困惑。

新要求:每次尝试登录失败后,显示错误消息。

每当发生身份验证错误时,都会引发异常。 默认情况下,表单身份验证过滤器会捕获异常并将其类名称存储在request参数中。 由于我们希望自定义发送到页面的数据,因此我们必须扩展FormAuthenticationFilter并重写setFailureAttribute方法:

@Override
protected void setFailureAttribute(ServletRequest request, AuthenticationException ae) {String message = ae.getMessage();request.setAttribute(getFailureKeyAttribute(), message);
}

用VerboseFormAuthenticationFilter替换表单授权过滤器,并将其配置为使用'simpleShiroApplicationLoginFailure'请求属性来保存错误信息:

[main]
# replace form authentication filter with verbose filter
authc = org.meri.simpleshirosecuredapplication.servlet.VerboseFormAuthenticationFilter
# request parameter with login error information; if not present filter assumes 'shiroLoginFailure'
authc.failureKeyAttribute=simpleShiroApplicationLoginFailure

在login.jsp页面中显示错误:

<% String errorDescription = (String) request.getAttribute("simpleShiroApplicationLoginFailure");if (errorDescription!=null) {
%>
Login attempt was unsuccessful: <%=errorDescription%>
<% }
%>

当心:真实的应用程序不应显示太多的登录错误信息。 消息“尝试登录失败。” 没有更多信息通常就足够了。

散列密码

当前应用程序版本的所有密码均以纯文本格式存储。 最好只存储和比较密码哈希。

负责身份验证的对象称为领域 。 默认情况下,Shiro使用带可插入密码匹配器的IniRealm来比较密码。 我们将用ini的SHA-256哈希替换ini中的密码,并将IniRealm配置为使用SHA-256哈希匹配器。

生成密码的SHA-256哈希:

import org.apache.shiro.crypto.hash.Sha256Hash;public static void main(String[] args) {Sha256Hash sha256Hash = new Sha256Hash("heslo");System.out.println(sha256Hash.toHex());
}

将Shiro配置为比较密码哈希而不是密码本身:

[main]
# define matcher matching hashes instead of passwords
sha256Matcher = org.apache.shiro.authc.credential.HashedCredentialsMatcher
sha256Matcher.hashAlgorithmName=SHA-256# enable matcher in iniRealm (object responsible for authentication)
iniRealm.credentialsMatcher = $sha256Matcher

用密码哈希替换用户密码:

[users]
administrator=56b1db8133d9eb398aabd376f07bf8ab5fc584ea0b8bd6a1770200cb613ca005, Administrator
friendlyrepairmen=56b1db8133d9eb398aabd376f07bf8ab5fc584ea0b8bd6a1770200cb613ca005, repairmen
unfriendlyrepairmen=56b1db8133d9eb398aabd376f07bf8ab5fc584ea0b8bd6a1770200cb613ca005, repairmen
mathematician=56b1db8133d9eb398aabd376f07bf8ab5fc584ea0b8bd6a1770200cb613ca005, scientist
physicien=56b1db8133d9eb398aabd376f07bf8ab5fc584ea0b8bd6a1770200cb613ca005,  scientist
productsales=56b1db8133d9eb398aabd376f07bf8ab5fc584ea0b8bd6a1770200cb613ca005,        sales
servicessales=56b1db8133d9eb398aabd376f07bf8ab5fc584ea0b8bd6a1770200cb613ca005,  sales

注意:无法在ini配置中指定salt。

创建注销页面

具有登录功能的任何应用程序也应具有注销功能。 使用Shiro注销当前用户很容易,请使用以下命令:

//acquire currently logged user and log him out
SecurityUtils.getSubject().logout();

注销页面如下所示:

<%@ page import="org.apache.shiro.SecurityUtils" %>
<% SecurityUtils.getSubject().logout();%>
You have succesfully logged out.

添加授权

我们通过向应用程序添加授权来结束第一部分。 我们从限制用户访问页面开始。 任何用户都不能看到其他部门的页面。 由于用户仍然能够使用“所有应用程序功能”页面或在浏览器中编辑URL来执行任何操作,因此这仅为项目提供了部分安全性。 我们将其称为页面级授权。

然后,我们限制了用户自己执行操作的能力。 即使用户打开“所有应用程序功能”页面或在浏览器中编辑URL,也将只允许他执行其部门特定的功能。 我们将其称为功能级别授权。

新要求:用户无法查看不属于他的部门的页面。 用户只能执行其部门职能。 以前的规则唯一的例外是管理员,管理员可以执行管理和修复功能。

页面授权

页面级授权是通过角色过滤器完成的。 过滤器的参数部分可以包含任意数量的角色。 登录的用户只有拥有所有提供的角色,才能访问页面。

像往常一样,在Shiro.ini文件中配置角色过滤器:

[urls]
# force ssl for login page
/simpleshirosecuredapplication/account/login.jsp=ssl[8443],authc# only users with some roles are allowed to use role-specific pages
/simpleshirosecuredapplication/repairmen/**=authc, roles[repairman]
/simpleshirosecuredapplication/sales/**=authc, roles[sales]
/simpleshirosecuredapplication/scientists/**=authc, roles[scientist]
/simpleshirosecuredapplication/adminarea/**=authc, roles[Administrator]# enable authc filter for the all application pages; as Shiro reads urls from up to down, must be last
/simpleshirosecuredapplication/**=authc

测试安全性是否有效:以任何销售用户身份登录,单击“主页”,然后单击“维修人员页面”链接。 您会看到一个难看的错误。

我们完成页面授权并将错误替换为重定向到错误页面。 默认的Shiro过滤器具有属性validateUrl。 如果发生未经授权的访问,过滤器会将用户重定向到指定的url。

[main]
# redirect to an error page if user does not have access rights
roles.unauthorizedUrl = /simpleshirosecuredapplication/account/accessdenied.jsp

accessdenied.jsp:

<body>
Sorry, you do not have access rights to that area.
</body>

功能授权

现在所有部门页面均已安全。 但是,任何用户仍可以在“所有应用程序功能”页面上执行任何功能。 此外,任何登录的用户都可以编辑url,从而可以执行任何操作。 例如,如果您以销售人员身份登录并将https:// localhost:8443 / simpleshirosecuredapplication / masterservlet?action = MANAGE_REPAIRMEN放入url中,则该应用程序也将执行管理修复功能(然后将引发空指针异常,但存在安全漏洞)已经完成了)。

我们为每个功能分配唯一的权限 。 它们分为几组:

  • 所有权限都在“功能”组中,
  • 所有管理权限都在“管理”组中,
  • 所有修复权限都在“修复”组中,
  • 所有销售权限都在“销售”组中,
  • 所有科学许可都在“科学”组中。

Shiro支持表示为字符串的多级权限。 级别用符号“:”分隔。 例如,“功能:管理:修理工”具有三个级别:“功能”,“管理”和“修理工”。 多级权限允许轻松进行权限分组。 例如,科学组属于功能组,并且包含三个权限:

  • 职能:科学:研究,
  • 功能:科学:写作文章,
  • 职能:科学:准备谈话。

操作将在完成记录的用户权限之前对其进行验证:

public String doIt() {String neededPermission = getNeededPermission();// acquire logged user and check permissionif (SecurityUtils.getSubject().isPermitted(neededPermission))return "Function " + getName() + " run succesfully.";throw new UnauthorizedException("Logged user does not have " + neededPermission + " permission");
}

注意:实现相同目标的另一种方法是通过注释。

PerformFunctionAndGoBackServlet servlet捕获授权异常并将其转换为错误消息:

private String performAction(String actionName) {try {Actions action = findAction(actionName);String result = action == null ? null : action.doIt();log.debug("Performed function with result: " + result);return result;} catch (ShiroException ex) {log.debug("Function failed with " + ex.getMessage() + " message.");return "Error: " + ex.getMessage();}
}

最后,我们需要在Shiro.ini文件中配置角色的权限。 Shiro支持通配符以获得多级权限。 因此,我们不必分别指定每个部门的许可:

[roles]
# members of departments should be able to perform all departmental functions
sales=functions:sale:*
scientist=functions:science:*
repairman=functions:repair:*# administrators are able to do all management functions and repair functions
Administrator=functions:manage:*,functions:repair:*

您现在可以在“所有应用程序功能”页面上尝试功能。 如果登录的用户没有所需的权限,则会在页面顶部显示错误消息。 此外,如果您以销售人员身份登录并尝试入侵https:// localhost:8443 / simpleshirosecuredapplication / masterservlet?action = MANAGE_REPAIRMEN,则会在控制台中看到错误消息(而不是成功消息)。

结束

最终的应用程序可以在Github上的“ static_authentication_and_authorization”分支中找到。

在第二部分中,我们将创建自定义领域,并将用户,密码,角色和权限从ini文件移动到数据库。 第三部分专门介绍Apache Shiro加密软件包。

参考: Apache Shiro第1部分– JCG合作伙伴 Maria Jurcovicova的基础知识,来自This is Stuff博客。

翻译自: https://www.javacodegeeks.com/2012/05/apache-shiro-part-1-basics.html

Apache Shiro第1部分–基础相关推荐

  1. apache shiro_Apache Shiro第1部分–基础

    apache shiro Apache Shiro (最初称为JSecurity)是Java安全框架. 它被接受并于2010年成为Apache顶级项目.它的目标是功能强大且易于使用. 该项目正在积极开 ...

  2. Apache Shiro教程

    跟开涛学系列: 来自开涛的Apache Shiro教程:http://jinnianshilongnian.iteye.com/blog/2018398 附带的代码例子:https://github. ...

  3. apache shiro jar包_只需要6个步骤,springboot集成shiro,并完成登录

    小Hub领读: 导入jar包,配置yml参数,编写ShiroConfig定义DefaultWebSecurityManager,重写Realm,编写controller,编写页面,一气呵成.搞定,是个 ...

  4. Apache Shiro和Spring Security的详细对比

    参考资料: 1)Apache Shiro Apache Shiro:http://shiro.apache.org/ 在Web项目中应用 Apache Shiro:http://www.ibm.com ...

  5. 在Spring MVC中使用Apache Shiro安全框架

    我们在这里将对一个集成了Spring MVC+Hibernate+Apache Shiro的项目进行了一个简单说明.这个项目将展示如何在Spring MVC 中使用Apache Shiro来构建我们的 ...

  6. vb6编写用户权限_仅需三行代码,即可让Apache Shiro接管Swagger权限认证

    有很多文章提到,在生产环境中需要关闭Swagger功能,防止系统资源泄露.今天,我结合自己开发过程中的经验,分享一个只需几行代码便可实现让Apache Shiro接管Swagger认证和授权的方法.如 ...

  7. apache shiro怎么升级_Springboot整合Shiro之授权

    第二条为推广文章,阅读一次0.3kuai, 收入用于网站服务器及资源索取. Shiro是我们常用的一个权限管理框架,本文的重点是来介绍下在SpringBoot环境下我们怎么来使用Shiro. 一.添加 ...

  8. Apache Shiro第3部分–密码学

    除了保护网页和管理访问权限外, Apache Shiro还执行基本的加密任务. 该框架能够: 加密和解密数据, 哈希数据, 生成随机数. Shiro没有实现任何加密算法. 所有计算都委托给Java密码 ...

  9. Apache Shiro第2部分–领域,数据库和PGP证书

    这是致力于Apache Shiro的系列文章的第二部分. 我们从简单的不安全Web应用程序开始了上一部分 . 完成后,该应用程序具有基本的身份验证和授权. 用户可以登录和注销. 所有网页和按钮均已分配 ...

最新文章

  1. 看闯关东原来知道古代已经十六进制了
  2. spoj Simple Average
  3. C语言 实现一个函数判断year是不是润年
  4. php9宫格抽奖程序_php抽奖算法(适用于九宫格、大转盘)
  5. jdk的selector(2)channel的注册
  6. python unicodeencodeerror_Python发起请求提示UnicodeEncodeError错误代码解决方法
  7. “梧桐杯”中国移动大数据应用创新大赛 - 智慧城市赛道baseline
  8. 如何优雅的抢占别人的显卡?
  9. DIV 半透明层、 CSS实现网页 背景半透明
  10. ASIC设计流程相关
  11. 在WordPress中重新排序博客文章的4种简单方法(循序渐进)
  12. algorithm2e笔记,记录一下常规操作
  13. 三、jQuery 中的 DOM 操作(超详细)
  14. html中 a链接的默认样式,超链接的默认样式
  15. Yolo v3的学习
  16. 总结一下,小灰的2020年!
  17. 『2月特刊』伟大的朋友丨拿破仑(1)
  18. matlab x(n)16点DFT,[基于MATLAB的数字信号处理实例分析.doc
  19. 信号完整性分析---串扰和反射
  20. url如何拼接参数格式 ? 用和? =拼接

热门文章

  1. 如何评价分类模型性能?(足球荔枝)
  2. libgdx和unity_libgdx和Kotlin –类[2D平台原型]
  3. java改变变量编码方式_Java 8中的5个功能将改变您的编码方式
  4. q7goodies事例_Java 8 Friday Goodies:Lambda和排序
  5. 初始化创建画布_使用HTML5,画布和开放数据创建全球降水(雨)可视化
  6. Apache Spark Job的剖析
  7. Java正成为COBOL的一部分-它将成为COBOL的一部分吗?
  8. Java命令行界面(第25部分):JCommando
  9. 用Java解析:您可以使用的所有工具和库
  10. java线程死亡_Java模因拒绝死亡