设为首页 收藏本站
查看: 770|回复: 0

[经验分享] Apache Shiro在Web中的应用(转)

[复制链接]

尚未签到

发表于 2017-1-6 08:04:06 | 显示全部楼层 |阅读模式
摘自http://www.open-open.com/home/space-53513-do-blog-id-5479.html
Shiro 是一个 Apache Incubator 项目,旨在简化身份验证和授权。本文只是我对shiro的初步认识,有不对的请大虾指正,谢谢!


基本概念

在对系统进行安全保障时,有两个安全性元素非常重要:身份验证和授权。虽然这两个术语代表的是不同的含义,但出于它们在应用程序安全性方面各自的角色考虑,它们有时会被交换使用。

身份验证 (我们平常接触较多的就是登录)指的是验证用户的身份。在验证用户身份时,需要确认用户的身份的确如他们所声称的那样。在大多数应用程序中,身份验证是通 过用户名和密码的组合完成的。只要用户选择了他人很难猜到的密码,那么用户名和密码的组合通常就足以确立身份。但是,还有其他的身份验证方式可用,比如指 纹、证书和生成键。

一旦身份验证过程成功地建立起身份,授权 (我理解的就是权限管理与控制)就会接管以便进行访问的限制或允许。所以,有这样的可能性:用户虽然通过了身份验证可以登录到一个系统,但是未经过授权,不准做任何事情。还有一种可能是用户虽然具有了某种程度的授权,却并未经过身份验证。

在为应用程序规划安全性模型时,必须处理好这两个元素以确保系统具有足够的安全性。身份验证是应用程序常见的问题(特别是在只有用户和密码组合的情 况下),所以让框架来处理这项工作是一个很好的做法。合理的框架可提供经过测试和维护的优势,让您可以集中精力处理业务问题,而不是解决其解决方案已经实 现的问题。

Apache Shiro 提供了一个可用的安全性框架,各种客户机都可将这个框架应用于它们的应用程序。本文中的这些例子旨在介绍 Shiro 并着重展示对用户进行身份验证的基本任务。


初识shiro

Shiro 是一个用 Java 语言实现的框架,通过一个简单易用的 API 提供身份验证和授权。使用 Shiro,您就能够为您的应用程序提供安全性而又无需从头编写所有代码。

由于 Shiro 提供具有诸多不同数据源的身份验证,以及 Enterprise Session Management,所以是实现单点登录(SSO)的理想之选 — 大型企业内的一个理想特性,因为在大型企业内,用户需要在一天内经常登录到并使用不同系统。这些数据源包括 JDBC、LDAP、 Kerberos 和 Microsoft® Active Directory® Directory Services (AD DS)。

Shiro 的 Session 对象允许无需 HttpSession 即可使用一个用户会话。通过使用一个通用的Session 对象,即便该代码没有在一个 Web 应用程序中运行,仍可以使用相同的代码。没有对应用服务器或 Web 应用服务器会话管理的依赖,您甚至可以在命令行环境中使用 Shiro。换言之,使用 Shiro 的 API 编写的代码让您可以构建连接到 LDAP 服务器的命令行应用程序并且与 web 应用程序内用来访问 LDAP 服务器的代码相同。


Shiro在Web中的应用

将shiro整合到Web中最简单的方式就是在web.xml文件中配置一个Servlet ContextListener的监听器和Filter过滤器。实例代码如下:
01<listener>
02    <listener-class>org.apache.shiro.web.env.EnvironmentLoaderListener</listener-class>
03</listener>
04
05...
06
07<filter>
08    <filter-name>ShiroFilter</filter-name>
09    <filter-class>org.apache.shiro.web.servlet.ShiroFilter</filter-class>
10</filter>
11  
12<filter-mapping>
13    <filter-name>ShiroFilter</filter-name>
14    <url-pattern>/*</url-pattern>
15</filter-mapping>
以上的配置是假定shiro.ini的配置文件是放在以下两个位置下的(哪个先找到就用哪个):

    1. /WEB-INF/shiro.ini

    2. classpath的根目录

以上的代码做了如下的工作:

    EnvironmentLoaderListener初始化一个Shiro用的WebEnvironment实例(这个实例包括Shiro运行要用的任何东西,包含SecurityManager)并且让ServletContext可以访问它。可以在任何时刻调用WebUtils.getRequiredWebEnvironment(servletContext)语句获取WebEnvironment。
    ShiroFilter将用WebEnvironment为所有的经过滤的request执行所有的安全保障操作。
    最后,filter-mapping用以确保所有的请求通过ShiroFilter过滤。

注:建议将ShiroFilter filter-mapping声明在其他的filter-mapping声明之前,以确保Shiro也作用于那些filter。


Web INI 配置

默认情况下,初始化Shiro时,Shiro会自动按顺序搜索/WEB-INF/shiro.ini和classpath:shiro.ini位置下的.ini配置,然后用最先找到的那个。

如果配置较少,可以不用另外的.ini文件,而将INI配置在web.xml中。下面的配置就是将shiro的配置配置在web.xml中:
01<tt><listener>
02    <listener-class>org.apache.shiro.web.env.EnvironmentLoaderListener</listener-class>
03</listener>
04
05...
06  
07<filter>
08    <filter-name>ShiroFilter</filter-name>
09    <filter-class>org.apache.shiro.web.servlet.ShiroFilter</filter-class>
10    <init-param>
11           <param-name>config</param-name>
12           <param-value>
13                [users]
14                # format: username = password, role1, role2, ..., roleN
15                User1 = 123456
16                Manager1 = 123456, Manager
17                [filters]
18                [urls]
19                /* = authc
20           </param-value>
21     </init-param>
22</filter>
23
24<filter-mapping>
25    <filter-name>ShiroFilter</filter-name>
26    <url-pattern>/*</url-pattern>
27</filter-mapping></tt>
Web INI配置标准的有[main],[users],[roles],[urls]部分(具体如何配置可查看官方文档),下面是一个连接MySql数据库的配置示例:
01[main]
02ds = com.mysql.jdbc.jdbc2.optional.MysqlDataSource
03ds.serverName = 127.0.0.1
04ds.user = root
05ds.password = root
06ds.databaseName = test
07ds.url = jdbc:mysql://127.0.0.1:3306/test
08jdbcRealm = org.apache.shiro.realm.jdbc.JdbcRealm
09jdbcRealm.permissionsLookupEnabled = true
10jdbcRealm.authenticationQuery = SELECT password FROM ho_user WHERE name = ?
11jdbcRealm.userRolesQuery = SELECT role FROM ho_user WHERE name = ?
12jdbcRealm.permissionsQuery = SELECT permission FROM ho_user WHERE name = ?
13jdbcRealm.dataSource = $ds
14
15authc.loginUrl = /common/login.jsp
16perms.unauthorizedUrl = /common/login.jsp
17roles.unauthorizedUrl = /common/login.jsp
18
19[urls]
20/action/* = authc
21/admin/**=authc,perms[high]
22/system/**=authc,perms[high]

说明:

    jdbcRealm.dataSource = $ds指定jdbcRealm的数据源是前面配置的数据库ds。
    jdbcRealm.authenticationQuery,jdbcRealm.userRolesQuery,jdbcRealm.permissionsQuery 配置行是jdbc的与查询语句,它告诉shiro从何处获取授权的配置。它们都是用查询后的记录的第一个字段进行验证 的,authenticationQuery是查询后取第一条记录的第一个字段(这里是password字段)进行验证;userRolesQuery是用查询后的第一个字段(这里是role字段)作为所属的角色的(可以有多条记录即多个角色);permissionsQuery同userRolesQuery一样查询后可以有多条记录,但也是取第一个字段作为权限字符串。
    authc.loginUrl = /common/login.jsp是指定如果验证失败则页面跳转到/common/login.jsp下,perms.unauthorizedUrl = /common/login.jsproles.unauthorizedUrl = /common/login.jsp同理。
    [urls] 里的配置就是对特定的url进行授权。/admin/**=authc,perms[high],是对匹配/admin/**的url配置权限,进入此 url须通过authc和perms[high]验证(authc和perms都是系统内置的过滤器。authc告诉shiro,进入此url,必须是已 验证的登录用户;perms[high] 是权限限定符,perms是内置的过滤器,high是通过jdbcRealm.permissionsQuery查询出来的权限字符串,只有用户拥有该字 符串的权限,才能获得访问授权。如果针对角色授权,可以是/admin/**=authc,roles[admin])。

附内置过滤器:

过滤器名




anon


org.apache.shiro.web.filter.authc.AnonymousFilter

authc


org.apache.shiro.web.filter.authc.FormAuthenticationFilter

authcBasic


org.apache.shiro.web.filter.authc.BasicHttpAuthenticationFilter

logout


org.apache.shiro.web.filter.authc.LogoutFilter

noSessionCreation


org.apache.shiro.web.filter.session.NoSessionCreationFilter

perms


org.apache.shiro.web.filter.authz.PermissionsAuthorizationFilter

port


org.apache.shiro.web.filter.authz.PortFilter

rest


org.apache.shiro.web.filter.authz.HttpMethodPermissionFilter

roles


org.apache.shiro.web.filter.authz.RolesAuthorizationFilter

ssl


org.apache.shiro.web.filter.authz.SslFilter

user


org.apache.shiro.web.filter.authc.UserFilter


Shiro应用

配置好Web INI后,就能将其应用在Web中了,我们可以看看有了Shiro后,安全验证时多么的简便。



假设有一个LoginAction,只需三句语句就能实现验证
01public String execute() throws Exception {
02    try {
03            AuthenticationToken token = new UsernamePasswordToken(username,password);//username和password是从表单提交过来的
04              Subject currentUser = SecurityUtils.getSubject();
05            currentUser.login(token);
06            return SUCCESS;
07    }catch (Exeception e){
08            Return ERROR;
09    }
10}
只需两句话就能实现LogoutAction的动作
1public String execute() throws Exception {
2            Subject currentUser = SecurityUtils.getSubject();
3            currentUser.logout();
4            return SUCCESS;
5}

注:SecurityUtils 对象是一个 singleton,这意味着不同的对象可以使用它来获得对当前用户的访问。一旦成功地设置了这个SecurityManager,就可以在应用程序不同部分调用SecurityUtils.getSubject() 来获得当前用户的信息。



补充说明:

上述代码中用到了Subject和UsernamePasswordToken。这里增加一点Shiro的概念。

    Subject 是安全领域术语,除了代表人,它还可以是应用。在单应用中,可将其视为 User 的同义词。
    Principal 是 Subject 的标识,一般情况下是唯一标识,比如用户名。
    用户令牌。在 Shiro 术语中,令牌 指的是一个键,可用它登录到一个系统。最基本和常用的令牌是 UsernamePasswordToken,用以指定用户的用户名和密码。UsernamePasswordToken 类实现了AuthenticationToken 接口,它提供了一种获得凭证和用户的主体(帐户身份)的方式。UsernamePasswordToken 适用于大多数应用程序,并且您还可以在需要的时候扩展AuthenticationToken 接口来将您自己获得凭证的方式包括进来。例如,可以扩展这个接口来提供您应用程序用来验证用户身份的一个关键文件的内容。

更多的认证用法,请参考官方文档。

更多的授权用法,请参考官方文档。


JSP/GSP标签库

Shiro提供了JSP/GSP的标签库,这使得我们很容易能够在JSP,JSTL或GSP页面的控制基于Subject的状态的输出。



标签库的描述符(Tag Library Descriptor (TLD))在shiro-web.jar 的META-INF/shiro.tld下定义。要引用这些标签,只需在JSP页面的头部添加下面的语句:
1<tt><%@ taglib prefix="shiro" uri="http://shiro.apache.org/tags" %></tt>
如定义一个pag_header.jsp如下:
01<%@ taglib prefix="shiro" uri="http://shiro.apache.org/tags" %>
02<div id="page_header">
03      <div id="page_heading">Hello World</div>
04      <div id="page_headerlinks">
05            <ul>
06                  <li>
07                  <shiro:guest>
08                  <a href="/common/login.jsp">Login Now</a>
09                  </shiro:guest>
10                  <shiro:user>
11                  Welcome, <shiro:principal />
12                   </shiro:user>
13                  </li>
14                  <script>
15                        var username = '<shiro:principal/>';
16                  </script>
17                  <li>
18                  <shiro:guest>
19                  <a href="/common/register.jsp">Register Now</a>
20                  </shiro:guest>
21                  <shiro:user>
22                               <a href="Logout.action">Log out</a>
23                  </shiro:user>
24                  </li>
25            </ul>
26      </div>
27      <div class="clearthis"> </div>
28</div>

说明:guest标签只用于显示当前Subject被认为是“guest”的Subject内容。通常用于显示没有登录的内容。user标签只用于 显示当前Subject被认为是“user”的Subject内容。通常用于显示已经登录的内容。一般情况下,两者是互斥的,只显其一。

更多标签用法,参见官方文档。

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-324438-1-1.html 上篇帖子: Apache Shiro在Web中的应用 下篇帖子: Apache web服务器架设实战
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表