2.Shiro简介
2.1.是什么shiro?
Apache Shiro是一个强大且易用的Java安全框架,有身份验证、授权、密码学和会话管理。使用Shiro的易于理解的API,您可以快速、轻松地获得任何应用程序,从最小的移动应用程序到最大的网络和企业应用程序。
Spring security 重量级安全框架
Apache Shiro轻量级安全框架
2.2.shiro能干什么?
Shiro 开发团队称为“应用程序的四大基石” ——身份验证,授权,会话管理和加密作为其目标。
Authentication(身份认证):
有时也简称为“登录”,这是一个证明用户是他们所说的他们是谁的行为。
Authorization(授权):
访问控制的过程,也就是绝对“谁”去访问“什么”权限。
Session Management:管理用户特定的会话,即使在非 Web 或 EJB 应用程序。
Cryptography:通过使用加密算法保持数据安全同时易于使用。
也提供了额外的功能来支持和加强在不同环境下所关注的方面,尤其是以下这些:
Web Support: Shiro 的 web 支持的 API 能够轻松地帮助保护 Web 应用程序。
Caching:缓存是 Apache Shiro 中的第一层公民,来确保安全操作快速而又高效。
Concurrency: Apache Shiro 利用它的并发特性来支持多线程应用程序。
Testing:测试支持的存在来帮助你编写单元测试和集成测试,并确保你的能够如预期的一样安全。
“Run As”:一个允许用户假设为另一个用户身份(如果允许)的功能,有时候在管理脚本很有用。
“Remember Me”:在会话中记住用户的身份,所以他们只需要在强制时候登录。
2.3.架构
2.3.1.Shiro外部来看
从外部来看Shiro,即从应用程序角度来如何使用shiro来完成工作(认证、授权等)。
2.3.2.Shiro内部看
即shiro内部夹走
3.Shiro入门
前提:要一个Java Project
3.1.导入jar
3.2.拷贝资源
resources下面两个配置文件
log4j.properties
shiro.ini
java下面一个java文件
Quickstart.java
3.3.测试
Session数据
登录
授权
public class Quickstart {
private static final transient Logger log = LoggerFactory.getLogger(Quickstart.class);
public static void main(String[] args) {
//通过一个配置了realms,users,roles,permissions的ini的配置文件快速创建一个SecurityManager
Factory<SecurityManager> factory = new IniSecurityManagerFactory("classpath:shiro.ini");
SecurityManager securityManager = factory.getInstance();
//为了程序能偶正常运行,需要设置securityManager
SecurityUtils.setSecurityManager(securityManager);
//获取当前用户
Subject currentUser = SecurityUtils.getSubject();
//1 会话操作
Session session = currentUser.getSession();//获取session
session.setAttribute("someKey", "aValue");//在session中设置值
String value = (String) session.getAttribute("someKey");//从session中获取值
if (value.equals("aValue")) {
log.info("Retrieved the correct value! [" + value + "]");
//return;
}
//2 身份认证(登录)
//如果没有登录
if (!currentUser.isAuthenticated()) {
//把前台传入的用户名和密码创建一个UsernamePasswordToken
UsernamePasswordToken token = new UsernamePasswordToken("lonestarr", "vespa");
token.setRememberMe(true);
try {
//通过currentUser调用login传入UsernamePasswordToken执行登录操作,如果不正确就会抛出对应错误
currentUser.login(token);
} catch (UnknownAccountException uae) {
//用户不存在
log.info("There is no user with username of " + token.getPrincipal());
} catch (IncorrectCredentialsException ice) {
//密码不正确
log.info("Password for account " + token.getPrincipal() + " was incorrect!");
} catch (LockedAccountException lae) {
//账号被锁定
log.info("The account for username " + token.getPrincipal() + " is locked. " +
"Please contact your administrator to unlock it.");
}
//其他异常-AuthenticationException是上面一样的父类
// ... catch more exceptions here (maybe custom ones specific to your application?
catch (AuthenticationException ae) {
//unexpected condition? error?
}
}
//say who they are:
//print their identifying principal (in this case, a username):
log.info("User [" + currentUser.getPrincipal() + "] logged in successfully.");
//3 权限
//判断当前用户是否拥有该角色
if (currentUser.hasRole("schwartz")) {
log.info("May the Schwartz be with you!");
} else {
log.info("Hello, mere mortal.");
}
//测试权限 lightsaber:*
if (currentUser.isPermitted("lightsaber:weild")) {
log.info("You may use a lightsaber ring. Use it wisely.");
} else {
log.info("Sorry, lightsaber rings are for schwartz masters only.");
}
//a (very powerful) Instance Level permission:
if (currentUser.isPermitted("winnebago:drive:eagle5")) {
log.info("You are permitted to 'drive' the winnebago with license plate (id) 'eagle5'. " +
"Here are the keys - have fun!");
} else {
log.info("Sorry, you aren't allowed to drive the 'eagle5' winnebago!");
}
//all done - log out!
currentUser.logout();
System.exit(0);
}
}
3.4.总结
通过SecurityManger获取Suject
通过Subject来做事情:
获取Session-存值和获取值 Suject.getSession session.setAttribute session.getAttribute
认证(登录):
判断是否登录Suject.isAuthenticated
如果没有登录,通过用户名和密码创建UsernamePasswordToken
调用suject.login(UsernamePasswordToken)来进行登录判断
授权
判断是否具有某个角色subject .hasRole
判断是否有权限subject .isPrermited(resource:操作)
Log4j在项目中的使用
4.Shiro集成Spring
4.1.为什么要集成Spring
我们的项目基本都是通过Spring来管理bean的,如果要想使用Shiro,那就要把shiro集成到Spring。集成Spring的核心就是把框架的核心类(Subject,SecurityManager,Realm)交给Spring管理!
4.2.集成
4.2.1.准备Spring-web项目
拷贝ssm项目
4.2.2.集成
1)导入shiro-all-1.3.2.jar
参考官方demo做示例:
2)拷贝shiroFilter配置到web.xml
3)拷贝shiro Spring配置文件并集成到Spring
applicationContext.xml 改名为applicationContext-shiro.xml并在applicationContext.xml中导入
4)修改配置文件
5)测试
除了登录界面能够被正常访问,其他的都要跳转到登录界面!
4.3.小结
注意:需要一个Spring的环境,不能全部都在SpringMVC哪儿初始化
5.Authentication(身份认证)
5.1.引入
在集成Spring的例子中,只有登录页面是不需要登录可以直接访问。其他的页面需要认证(即登录)后才能访问,那怎么来实现登录认证,又叫做身份认证呢?
5.2.概念
做认证需要用户名和密码
认证流程:
5.3.详细步骤分析
要想实现登录,分前台和后台两部分:
前台:
实现一个login.jsp的页面,用来搜集登录信息(用户名和密码)!当点击登录时把登录信息提交到后台完成认证。
后台:
写一个Controller接收前台传入的登录信息,完成登录认证。
具体步骤如下:
1)创建LoginConroller,写一个方法接收前台登录请求并接受登录信息(用户名和密码)
2)获取当前的 Subject. 调用 SecurityUtils.getSubject();
3)测试当前的用户是否已经被认证. 即是否已经登录. 调用 Subject 的 isAuthenticated()
4)若没有被认证, 则把用户名和密码封装为 UsernamePasswordToken 对象
5)执行登录: 调用 Subject 的 login(AuthenticationToken) 方法.
6)自定义 Realm 的方法, 从数据库中获取对应的记录, 返回给 Shiro.
入门中使用的是Shiro自带的IniRealm,IniRealm从ini配置文件中读取用户的信息,大部分情况下需要从系统的数据库中读取用户信息,所以需要自定义realm。
实际上需要继承 org.apache.shiro.realm.AuthenticatingRealm 类
实现 doGetAuthenticationInfo(AuthenticationToken) 方法.
7)由 shiro 完成对密码的比对.
5.4.简单认证实现
5.5.简单实现总结
5.6.加密认证
分析:
1、密码不能明文保存到数据库 加密保存,比对也要加密比对,具体的比对CredentialsMatcher,默认使用就是SimpleCredentialsMatcher,不做加密的比对.要想做md5加密要使用HashedCredentialsMatcher,并且设置加密为md5
5.6.1.数据库加密保存
5.6.2.加密比对代码实现
5.7.盐值加密认证
为什么要使用盐值加密。盐值加密,更安全!
5.7.1.数据库要加密保存
5.7.2.认证时要支持盐值
5.8.盐值加密加次数认证
5.8.1.数据库要加密加盐加次数保存
5.8.2.认证时要支持次数
5.9.小结
普通认证
加密认证
加密加盐认证(采纳)