背景
目前比较流行的权限框架有Apache Shiro和 Spring Security。相比Spring Secrity, Shiro更加简单,概念相对好理解。同时,原有项目对于用户登录态,用户权限的管理都使用到了Shiro,因此选择Shiro作为一个权限框架的学习。
Shiro是什么
参考:官网: shiro.apache.org
Apache Shiro 是一个功能强大且易于使用的Java权限框架。Shiro可以完成认证、授权、加密、会话管理、与Web集成、缓存等。
为什么使用
易于使用:使用Shiro构建系统安全框架非常简单。就算第一次接触也可以快速掌握。
全面:Shiro 包含系统安全框架需要的功能,满足安全需求的“一站式服务”。
灵活:Shiro·可以在任何应用程序环境中工作。虽然它可以在·Web、EJB·和·IoC·环境中工作,但不需要依赖它们。Shiro·也没有强制要求任何规范,甚至没有很多依赖项。
强力支持Web:
Shiro·具有出色的·Web·应用程序支持,可以基于应用程序·URL·和·Web·协议(例如·REST)创建灵活的安全策略,同时还提供一组·JSP·库来控制页面输出。
兼容性强:
Shiro的设计模式使其易于与其他框架和应用程序集成。Shiro·与·Spring、Grails、Wicket、Tapestry、Mule、Apache·Camel、Vaadin·等框架无缝集成。
社区支持:Shiro·是Apache·软件基金会的一个开源项目,有完备的社区支持,文档支持。如果需要,像Katasoft这样的商业公司也会提供专业的支持和服务。
Shiro 与 SpringSecurity 的对比
1、Spring·Security·基于Spring·开发,项目若使用·Spring·作为基础,配合·SpringSecurity·做权限更加方便,而·Shiro·需要和·Spring·进行整合开发;
2、Spring·Security·功能比·Shiro·更加丰富些,例如安全维护方面;
3、Spring·Security·社区资源相对比·Shiro·更加丰富;
4、Shiro·的配置和使用比较简单,Spring·Security·上手复杂些,学习成本高;
5、Shiro·依赖性低,不需要任何框架和容器,可以独立运行.Spring·Security·依赖Spring 容器;
6、shiro·不仅仅可以使用在web中,它可以工作在任何应用环境中。在集群会话时Shiro最重要的一个好处或许就是它的会话是独立于容器的。
Shiro框架(Shiro外部来看)
了解应用程序是如何利用Shiro工作的。
Shiro框架(Shiro内部来看)
ApplicationCode:应用程序
Subject:主体:既可以是用户,也可以是应用程序。
SecurityManager:是整个框架的核心,协调多个功能组件一起发挥各自的作用,用于控制所有用户的权限功能。,主要模块有Authenticator(身份认证),Authorizer(授权验证)
Realm:用于封装从ini文件或数据库或缓存获取的认证信息,角色信息,权限信息,相当于数据源。
Session Manager:会话管理。
Cryptography:这个模块用于一些加密解密和哈希处理,Shiro对相关的算法做了封装,能够比较容易上手使用。
代码示例
在现在大多数应用都是利用SpringBoot搭建的,则该示例也是在Spring环境下。
- Spring整合Shiro:
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-spring-boot-web-starter</artifactId>
<version>1.9.1</version>
</dependency>
2. 为了简单起见,这里使用ini文件的方式来定义凭据和权限关系,在resources文件下创建shiro.ini文件。
shiro.ini内容
代码片段
自定义Realm--MyRealm.Class
//认证
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
//获取用户名
String username = authenticationToken.getPrincipal().toString();
String password = authenticationToken.getCredentials().toString();
//为了演示方便,就设定死了
String initUsername = username;
String password2 = "123";
AuthenticationInfo info = new SimpleAuthenticationInfo(
authenticationToken.getPrincipal(),
//实际是数据库取出的密码
password,
//密码加盐
ByteSource.Util.bytes("salt"),
authenticationToken.getPrincipal().toString()
);
return info;
ShiroConig.Class文件
@Configuration
public class ShiroConfig {
@Autowired
private MyRealm myRealml;
@Bean
public DefaultWebSecurityManager defaultSecurityManager(){
//1.创建DefaultWebSecurityManager 管理器
DefaultWebSecurityManager defaultWebSecurityManager = new DefaultWebSecurityManager();
//2.加密对象相关属性
// HashedCredentialsMatcher matcher = new HashedCredentialsMatcher();
// //2.1采用MD5加密
// matcher.setHashAlgorithmName("md5");
// //2.2迭代次数
// matcher.setHashIterations(3);
// //3.将加密对象存储到myRealm中
// myRealml.setCredentialsMatcher(matcher);
//4.将Realm设置进defaultWebSecurityManager中
defaultWebSecurityManager.setRealm(myRealml);
return defaultWebSecurityManager;
}
@Bean
public DefaultShiroFilterChainDefinition shiroFilterChainDefinition(){
DefaultShiroFilterChainDefinition defaultShiroFilterChainDefinition = new DefaultShiroFilterChainDefinition();
//设置不认证可以访问的资源
defaultShiroFilterChainDefinition.addPathDefinition("/myController/login","anon");
defaultShiroFilterChainDefinition.addPathDefinition("/login","anon");
//设置需要进行登录认证的拦截范围
defaultShiroFilterChainDefinition.addPathDefinition("/**","authc");
return defaultShiroFilterChainDefinition;
}
}
remember-me-功能
除此之外,Shiro·提供了记住我(RememberMe)的功能,比如访问一些网站时,关闭了浏览器,下次再打开时还是能记住你是谁,·下次访问时无需再登录即可访问。
1、基本流程(1)→首先在登录页面选中RememberMe然后登录成功;如果是浏览器登录,一般会把RememberMe的Cookie写到客户端并保存下来;(2)→关闭浏览器再重新打开;会发现浏览器还是记住你的;(3)→访问一般的网页服务器端,仍然知道你是谁,且能正常访问;((4)→但是,如果我们访问电商平台时,如果要查看我的订单或进行支付时,此时还是需要再进行身份认证的,以确保当前用户还是你.
在ShiroConfig.Class 添加
//设置Cookie属性
public SimpleCookie rememberMeCookie(){
SimpleCookie cookie = new SimpleCookie("rememberMe");
//设置跨域
cookie.setPath("/");
cookie.setHttpOnly(true);
cookie.setMaxAge(30*24*60*60);
return cookie;
}
//创建shiro的cookie管理对象
public CookieRememberMeManager rememberMeManager(){
CookieRememberMeManager cookieRememberMeManager = new CookieRememberMeManager();
cookieRememberMeManager.setCookie(rememberMeCookie());
//
cookieRememberMeManager.setCipherKey("adaffas".getBytes());
return cookieRememberMeManager;
}
//添加存在用户的过滤器(rememberMe) antPath:路径,defintion:相关操作
//登录用户才可以访问,包含remember me
defaultShiroFilterChainDefinition.addPathDefinition("/**","user");
Logout-功能
//配置登出过滤器
defaultShiroFilterChainDefinition.addPathDefinition("/logout","logout");
总结
1.shiro框架提供了很好的权限管理的功能,方便我们的集成使用,它既可以独立与Spring应用,也可以整合Spring使用,相比SpringSecurity更加灵活一些
2.shiro主要提供认证与授权功能
3.shiro主要由Subject(主体),SecurityManager(安全管理),Realm,Cryptography组成。
4.认证过程:
认证步骤说明:
- 首先调用Subject.login(token)进行登录,其会自动委托给SecurityManager,调用之前必须通过SecurityUtils.setSecurityManager()设置。
- SecurityManager负责真正的身份验证逻辑,它会委托给Authenticator进行身份验证。
- Authenticator才是真正的身份验证者,Shiro API中核心的身份认证入口点,此处可以自定义插入自己的实现。
- Authenticator可能会委托给相应的AuthenticationStrategy进行多Realm身份验证,默认ModularRealmAuthenticator会调用AuthenticationStrategy进行多Realm身份验证。
- Authenticator会把相应的token传入Realm,从Realm获取身份验证信息,如果没有返回或抛出异常表示身份验证失败了。此处可以配置多个Realm,将按照相应的顺序及策略进行访问。