想做一个关于权限管理的系统,了解到Apache Shiro比较适合,那么开始着手学习吧!
Apache Shiro是一个简单易用又强大的Java开源安全管理框架。
四大基石:
其他功能:
注意,Shiro不会去维护用户、维护权限,需要开发者自己去设计去提供,然后通过相关接口注入给Shiro。
import org.apache.shiro.subject.Subject;
import org.apache.shiro.SecurityUtils;
...
Subject currentUser = SecurityUtils.getSubject();
图源:http://greycode.github.io/shiro/doc/architecture.html
首先,应用代码通过Subject进行授权和验证,然后Subject委托给SecurityManager处理,我们需要给SecurityManager注入Realm,从而使SecurityManager得到合法的用户和权限进行判断。
当调用login方法时,SecurityManager会接受AuthenticationToken,然后分配到一个或多个Realms中执行身份验证。
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);
对于login失败也有相应的处理
Handle Failed Login
//Login:
try {
currentUser.login(token);
} catch (IncorrectCredentialsException ice) { …
} catch (LockedAccountException lae) { …
}
…
catch (AuthenticationException ae) {…
}
通过Subject API可以轻松地执行角色和权限检查。
方式一:Role check
if ( subject.hasRole(“administrator”) ) {
//show the ‘Create User’ button
} else {
//grey-out the button?
}
但是这种方式有一个巨大的弱点:无法在运行时添加/删除角色,如果在运行时改变了角色名称/配置,代码就会被破坏。所以如果需要在运行时可以增/删角色,需要使用另一种方法。
方式二: Permission check
if ( subject.isPermitted(“user:create”) ) {
//show the ‘Create User’ button
} else {
//grey-out the button?
}
这样,任何分配了“user:create”权限的角色都可以点击’Create User’按钮,并且这些角色和分配都可以在运行时修改。
方式三:Instance-Level Permission Check
if ( subject.isPermitted(“user:delete:jsmith”) ) {
//delete the ‘jsmith’ user
} else {
//don’t delete ‘jsmith’
}
这种方式可以更具体的控制权限
大多数安全框架仅提供了Authentication和Authorization功能,但是Shiro还提供了其他的功能。
Session session = subject.getSession();
如果使用JDK的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();
SHA-512散列和密码的Base64编码也一样很简单
String encodedPassword =
new Sha512Hash(password, salt, count).toBase64();
之前使用过JDK Cryptography API, 尤其是javax.crypto.Cipher这个类的开发人员都知道这是比较复杂的加密密码实现。
Shiro试图通过引入其CipherService API来简化加密密码的整个概念。
CipherService是一种简单,无状态的,线程安全的API,可以在一次方法调用中完整地加密或解密数据。我们只需提供密钥,然后根据需要进行加密或解密。
// use 256-bit AES encryption
AesCipherService cipherService = new AesCipherService();
cipherService.setKeySize(256);
//create a test key:
byte[] testKey = cipherService.generateNewKey();
//encrypt a file’s bytes:
byte[] encrypted =
cipherService.encrypt(fileBytes, testKey);
将Shiro设置为Web应用程序很简单。唯一需要的是在web.xml中定义一个Shiro Servlet过滤器
ShiroFilter in web.xml
<filter>
<filter-name>ShiroFilterfilter-name>
<filter-class>
org.apache.shiro.web.servlet.IniShiroFilter
filter-class>
filter>
<filter-mapping>
<filter-name>ShiroFilterfilter-name>
<url-pattern>/*url-pattern>
filter-mapping>
图源:http://greycode.github.io/shiro/doc/architecture.html
有一些在前面有较详细地介绍过,在这里就不再赘述了。
References: