shiro分析与应用

简介:

1、在设计系统安全验证时是否有些失意?

2、现有的java安全验证是否有点复杂?

 Apache Shiro提供了简单而又强大的系统验证方法。

下面逐一介绍Apache Shiro的:

  • 架构原理
  • 如何使用它

What is Apache Shiro?

Shiro提供了验证(authentication)、授权(authorization), 加密(cryptography), session管理(session management),并且可以用于任何系统的安全管理。

谁在用Shiro?

Shiro及其前身应用在了各种大小和各种行业的企业中,成为了Apache下的一个顶级项目。

Many open-source communities are using Shiro as well, for example, Spring, Grails, Wicket, Tapestry, Tynamo, Mule, and Vaadin, just to name a few.

Commercial companies like Katasoft, Sonatype, MuleSoft, one of the major social networks, and more than a few New York commercial banks use Shiro to secure their commercial software and websites.

架构

核心概念:主题(Subject), 安全管理(SecurityManager), and 领域(Realms)

Subject

可以理解为“用户”,这里没有起名为“用户”是因为“用户”一般指人。而Subject不仅仅指人,还可以是第三方的应用。  

 或者可以简单理解为"与软件交互的事物"。

你可以在系统的任务地方获取Shiro Subject:

import org.apache.shiro.subject.Subject;
import org.apache.shiro.SecurityUtils;
...
Subject currentUser = SecurityUtils.getSubject();

 一旦获取到了Subject,几乎可以满足了90%的用户应用:登录、注销、权限验证、session获取等。

SecurityManager

如果说Subject是对单个用户的安全管理,那么SecurityManager是对所有用的安全管理。

SecurityManager是Shiro框架的核心,它像一系列的“保护伞”,自动调用内部的安全组件。

当然一旦SecurityManager的相关配置设置好后,我们需要应对的只是Subject的API。

那我们如何来配置SecurityManger呢?这取决于您的业务系统。

如果是web应用,您可以在web.xml中配置Shiro Servlet Filter,它会帮您设置SecurityManger实例。如果是单机系统,需要使用不同配置方式。当然这里也提供多种不同方式的配置形式。

Shiro推荐的默认配置方式是“ini',简单、易读、依赖少。

Configuring Shiro with INI
[main]
cm = org.apache.shiro.authc.credential.HashedCredentialsMatcher
cm.hashAlgorithm = SHA-512
cm.hashIterations = 1024
# Base64 encoding (less text):
cm.storedCredentialsHexEncoded = false
iniRealm.credentialsMatcher = $cm

[users]
jdoe = TWFuIGlzIGRpc3Rpbmd1aXNoZWQsIG5vdCBvbmx5IGJpcyByZWFzb2
asmith = IHNpbmd1bGFyIHBhc3Npb24gZnJvbSBvdGhlciBhbXNoZWQsIG5vdCB

 上面配置中分了两个段落[main]、[users]

[main]中配置SecurityManager或其引用的对象。上面配置的了两个对象cm、iniRealm.

[users]用于简单系统或测试系统的用户配置。

上面配置演示,不在于讲解Shiro的配置文件段落,而是说明"ini"的配置方式。

Loading shiro.ini Configuration File
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.config.IniSecurityManagerFactory;
import org.apache.shiro.mgt.SecurityManager;
import org.apache.shiro.util.Factory;
...

//1. Load the INI configuration
Factory<SecurityManager> factory =
new IniSecurityManagerFactory("classpath:shiro.ini");

//2. Create the SecurityManager
SecurityManager securityManager = factory.getInstance();

//3. Make it accessible
SecurityUtils.setSecurityManager(securityManager);

Realms

Realm扮演着Shiro与系统中安全数据的桥梁的角色。系统真正执行安全认证交互的时候,shiro会检索系统中配置的realms,从而获取系统中的安全数据。

这样来看realm实质是security-specific DAO

在配置Shiro的realms时,至少要有一个认证或授权的realm。

realm配置时可以连接不同类型的datasource,譬如LADP、jdbc、properties、ini等等。当然也可以自定义realm以实现个性化的需求。

Example realm configuration snippet to connect to LDAP user data store 写道
[main]
ldapRealm = org.apache.shiro.realm.ldap.JndiLdapRealm
ldapRealm.userDnTemplate = uid={0},ou=users,dc=mycompany,dc=com
ldapRealm.contextFactory.url = ldap://ldapHost:389
ldapRealm.contextFactory.authenticationMechanism = DIGEST-MD5

上面介绍了怎么配置shiro环境,下面看看作为一个开发人员,怎样使用这种架构。

 

 认证(Authentication)

Shiro提供Subject-centric API,也就是几乎所有与shiro的交互是通过Subject来实现的,认证也不例外。

最常见的认证场景是通过用户提供的用户名和密码,验证用户是否能成功登录。在Shiro中直接调用Subject的login方法即可:

//1. Acquire submitted principals and credentials:
AuthenticationToken token =
new UsernamePasswordToken(username, password);
//2. Get the current Subject:
Subject currentUser = SecurityUtils.getSubject();

//3. Login:
currentUser.login(token);

 Subject执行认证动作时,SecurityManager会收到AuthenticationToken,并转发给一个或多个realm,每个realm都可以认证动作

但是,一旦验证失败,又该怎么获取失败结果呢?

可以使用AuthenticationException。

Handle Failed Login 写道
/3. Login:
try {
currentUser.login(token);
} catch (IncorrectCredentialsException ice) { …
} catch (LockedAccountException lae) { …
}

catch (AuthenticationException ae) {…
}

 

系统认证成功后,用户就可以访问系统了。但这种认证不意味着可以在系统中做任何事。

怎么限制一个用户可以在系统中做什么?

通过authorization(授权)来实现。

授权(Authorization)

授权是访问控制,以免有些用户在系统里胡作非为。

用户能做什么,一般由系统配置的用户角色来限定,Subject当然也定义了获取用户角色的简单方式:

Role Check
if ( subject.hasRole(“administrator”) ) {
//show the ‘Create User’ button
} else {
//grey-out the button?
}

 这中硬编码的方式缺点很明显,一旦角色名有了变化,就要重改代码。

Shiro提出来许可(permissions)的概念。一个permission就是一个功能的声明,例如:‘open a door’, ‘create a blog entry’, ‘delete the ‘jsmith’ user’, etc. 

Permission Check 写道
if ( subject.isPermitted(“user:create”) ) {
//show the ‘Create User’ button
} else {
//grey-out the button?
}

 上面这种方式,一旦角色或用户被赋予了“user:create”这种需要,就可以显示“Create User”按钮了。

Session管理(Session Management)

Shiro提供的Session管理有两个明显的优点:

  • 容器无关
  • 跨客户端技术
Subject’s Session
Session session = subject.getSession();
Session session = subject.getSession(boolean create);

 

非web应用也可以创建和使用session。

Session methods 写道
Session session = subject.getSession();
session.getAttribute(“key”, someValue);
Date start = session.getStartTimestamp();
Date timestamp = session.getLastAccessTime();
session.setTimeout(millis);
...

 

加密(Cryptography)

Shiro提供的加密目标是简单使用jdk提供的加密方法。

需要注意的事Shiro提供的加密与Subject是无关的,不用使用Subject的情况下也可以使用它的加密。

Shiro最关注的两点是:hash和cipher

使用Shiro提供的API要比直接使用jdk的api简单许多,一个简单的MD5加密:

JDK’s MessageDigest 
try {
MessageDigest md = MessageDigest.getInstance("MD5");
md.digest(bytes);
byte[] hashed = md.digest();
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
}
Shiro
String hex = new Md5Hash(myFile).toHex();

Web Support

通过配置filter基础shiro到web工程。

URL-Specific Filter Chains

复杂验证可以配置url的过滤链。

[urls]
/assets/** = anon
/user/signup = anon
/user/** = user
/rpc/rest/** = perms[rpc:invoke], authc
/** = authc

JSP Tag Library

Shiro提供多种jsp标签。

<%@ taglib prefix="shiro"
    uri="http://shiro.apache.org/tags" %>
...
<p>Hello
<shiro:user>
    <!-- shiro:principal prints out the Subject’s main
        principal - in this case, a username: -->
    <shiro:principal/>!
</shiro:user>
<shiro:guest>
    <!-- not logged in - considered a guest. Show
        the register link: -->
    ! <a href=”register.jsp”>Register today!</a>
</shiro:guest>
</p> 

猜你喜欢

转载自piabo2161978.iteye.com/blog/2304870