Apache Shiro(发音为“ shee-roh”,日语为“ castle”)是一种功能强大且易于使用的Java安全框架,可执行身份验证,授权,加密和会话管理,可用于保护任何应用程序的安全-从命令行应用程序,移动应用程序到最大的Web和企业应用程序。
Shiro提供了用于执行以下方面的应用程序安全性API(被称为应用程序安全性的4个基石):
Shiro还支持一些辅助功能,例如Web应用程序安全性,单元测试和多线程支持,但它们的存在是为了加强上述四个主要方面。
功能图如下:
Shiro实现原理:
Subject:应用代码直接交互的对象是Subject,也就是说Shiro的对外API核心就是Subject。Subject代表当前用户,这个用户不一定是一个具体的人与当前应用交互的任何东西都是Subject,如机器人等。与Subject的所有交互都会委托给SecurityManager。Subject如同一个门面,而SecurityManager才是实际的执行者。
SecurityManager:安全管理器,即所有与安全有关的操作都会与SecManager交互,并且他管理者所有的Subject,它是Shiro的核心,负责与Shiro的其他组件进行交互,它相当于SpringMVC的DispatcherServlet。
Realm:Shiro从Realm获取安全数据(如用户,角色,权限),即SeManager要验证用户身份,那么它需要从Realm获取相应的用户进行比较,来确定用户的身份是否合法。也需要从Realm得到用户相应的角色、权限,进行验证用户的操作是或否能够进行,可以把Realm看成DataSource。
简单来说,应用代码通过Subject来进行认证和授权,而Subject又委托给SecurityManager,我们需要给Shiro的SecurityManager注入Realm,从而让SecurityManager能得到合法的用户及权限进行判断。
在SpringBoot中使用Shiro,由于没有了xml配置文件,因此与Spring中有些区别。SpringBoot中使用Shiro实现权限管理步骤如下:
Shiro进行身份验证时从Realm中获取相应的身份信息进行验证,通过继承AuthorizingRealm类实现自定义Realm,并在自定义Realm中通过实现doGetAuthorizationInfo与doGetAuthenticationInfo方法进行自定义登录和授权认证。
public class ShiroDbRealm extends AuthorizingRealm {
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authcToken){
/**
* 登录认证
* 封装token
* 连接数据库
* return info
*/
}
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
/**
* 权限认证
* 拿到当前shiroUser对象
* 授权
* 设置当前用户权限
*/
}
ShiroConifg类为SpringBoot整合Shiro配置的核心类。ShiroConfig类中通过注解的方式依次实现SessionManager、SecurityManager、ShiroFilter、EhcacheManager。SessionManager是管理Shiro中Session生命周期的组件。在SecurityManager中配置自定义Realm。Apache Shiro权限管理与资源拦截的核心是通过Filter实现。
public class ShiroConfig {
@Bean
public DefaultWebSecurityManager securityManager(CookieRememberMeManager rememberMeManager, CacheManager cacheShiroManager, SessionManager sessionManager) {
/**
* 安全管理器
* return securityManager
*/
}
public DefaultWebSessionManager defaultWebSessionManager(CacheManager cacheShiroManager, GunsProperties gunsProperties) {
/**
* session管理器
* return sessionManager
*/
}
@Bean
public ShiroDbRealm shiroDbRealm() {
/**
* 项目自定义的Realm
*/
return new ShiroDbRealm();
}