1.什么是权限管理
<1.> 基本上涉及到用户参与的系统都要进行权限管理,权限管理属于系统安全的范畴,权限管理==实现对用户访问系统的控制==,按照安全规则或者安全策略控制用户可以访问而且只能访问自己被授权的资源。
<2.> 权限管理包括用户==身份认证==和==授权==两部分,简称==认证授权==。对于需要访问控制的资源用户首先经过身份认证,认证通过后用户具有该资源的访问权限方可访问。
1.1什么是身份认证
==身份认证==,就是判断一个用户是否为合法用户的处理过程。最常用的简单身份认证方式是系统通过核对用户输入的用户名和口令,看其是否与系统中存储的该用户的用户名和口令一致,来判断用户身份是否正确。对于采用指纹等系统,则出示指纹;对于硬件Key等刷卡系统,则需要刷卡。
1.2什么是授权
==授权,即访问控制==,控制谁能访问哪些资源。主体进行==身份认证后==需要分配权限方可访问系统的资源,对于某些资源没有权限是无法访问的
2.什么shiro框架
Apache Shiro 是一个强大易用的 Java 安全框架,提供了认证、授权、加密和session会话管理等功能,对于任何一个应用程序,Shiro 都可以提供全面的安全管理服务。并且相对于其他安全框架spring security,Shiro 要简单的多.
Shiro是apache旗下一个开源框架,它将软件系统的安全认证相关的功能抽取出来,实现用户身份认证,权限授权、加密、会话管理等功能,组成了一个通用的安全认证框架.
3.
为什么学shiro
Shiro可以非常容易的开发出足够好的应用,其不仅可以用在JavaSE(java基础)环境,也可以用在JavaEE(web开发)环境。Shiro可以帮助我们完成:认证、授权、加密、会话管理、与Web集成、缓存等。
4.使用shiro完成认证工作
4.1 shiro中认证的关键对象
Subject:主体访问系统的用户,主体可以是用户、程序等,进行认证的都称为主体;
Principal:身份信息----账号是主体(subject)进行身份认证的标识,标识必须具有唯一性,如用户名、手机号、邮箱地址等,一个主体可以有多个身份,但是必须有一个主身份(Primary Principal)。
credential:凭证信息---密码是只有主体自己知道的安全信息,如密码、证书等。
4.2 认证流程
4.3 代码
<1.>先不用数据库来进行身份认证,--我们ini文件,window系统文件,该文件中可以存放账号和密码.
(1) 创建一个maven java工程,导入shiro依赖
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-core</artifactId>
<version>1.9.0</version>
</dependency>
(2)创建ini文件
(3)测试代码
public class shiroTest01 {
public static void main(String[] args) {
//1.获取SecutiryManager对象
DefaultSecurityManager securityManager = new DefaultSecurityManager();
//2.读取ini文件 相当于读取数据源,以后用来读取数据库
IniRealm iniRealm = new IniRealm("classpath:shiro.ini");
//3.设置securityManager的realm
securityManager.setRealm(iniRealm);
//4.设置securityManager上下文有效
SecurityUtils.setSecurityManager(securityManager);
//5.获取subject主体对象 从SecurityUtils get到Subject主体
Subject subject= SecurityUtils.getSubject();
//try===监听器如果有异常就会直接抛出
try {
//这是login登录里面的参数,因为UsernamePasswordToken作用就是封装你Subject的身份信息和凭证信息
UsernamePasswordToken token = new UsernamePasswordToken("admin","123456");
//login校验登录
subject.login(token);
System.out.println("登录成功");
}catch (Exception e){
System.out.println("密码或账号失败");
}
}
}
4.4认证的原理
流程:1.Subject:主题登录信息提交给2.SecurityManager,3.认证器Authenticator根据你的realm提供的数据进行认证.realm==与数据源交互的类
5.授权
6.修改代码
package com.yk.demo01;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.mgt.DefaultSecurityManager;
import org.apache.shiro.realm.text.IniRealm;
import org.apache.shiro.subject.Subject;
public class shiroTest01 {
public static void main(String[] args) {
//1.获取SecutiryManager对象
DefaultSecurityManager securityManager = new DefaultSecurityManager();
//2.读取ini文件 相当于读取数据源,以后用来读取数据库
IniRealm iniRealm = new IniRealm("classpath:shiro.ini");
//3.设置securityManager的realm
securityManager.setRealm(iniRealm);
//4.设置securityManager上下文有效
SecurityUtils.setSecurityManager(securityManager);
//5.获取subject主体对象 从SecurityUtils get到Subject主体
Subject subject= SecurityUtils.getSubject();
//try===监听器如果有异常就会直接抛出
try {
//这是login登录里面的参数,因为UsernamePasswordToken作用就是封装你Subject的身份信息和凭证信息
UsernamePasswordToken token = new UsernamePasswordToken("admin","123456");
//login校验登录
subject.login(token);
System.out.println("登录成功");
}catch (Exception e){
System.out.println("密码或账号失败");
}
//退出功能
subject.logout();
System.out.println("===================登录后================");
// 验证登录认证是否通过
boolean authenticated = subject.isAuthenticated();
if (authenticated){
//判断当前登录者是否具有user:query权限,而现在我们所有的内容都封装到subject中
boolean permitted = subject.isPermitted("user:query");
System.out.println(permitted);
//从角色角度
boolean b = subject.hasRole("role1");
System.out.println(b);
}else {
System.out.println("请先认证"); }
}
}
7.认证的底层源码
在这个类下
8.自定义Realm 认证
package com.yk.demo01;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
import org.apache.shiro.realm.AuthenticatingRealm;
public class MyRealm extends AuthenticatingRealm {
private UserService userService=new UserService();
//该方法用于完成认证的功能
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
//1.根据token获取账号
String username = (String) authenticationToken.getPrincipal();
//2.根据账号查询用户信息
User user = userService.findByUsername(username);
if(user!=null){
//从数据库中获取的密码
SimpleAuthenticationInfo info = new SimpleAuthenticationInfo(user,user.getPassword(),this.getName());
return info;
}
return null;
}
}
9.加密
shiro它提供了很多中加密器。其他使用最多就是HashedCredentialsMatcher。它的底层使用的还是Md5加密。了解一下MD5加密
package com.yk.demo02;
import org.apache.shiro.crypto.hash.Md5Hash;
public class Test03 {
public static void main(String[] args) {
//source:需要加密的明文
Md5Hash md5Hash = new Md5Hash("123456");
System.out.println(md5Hash);//e10adc3949ba59abbe56e057f20f883e密文---默认md5加密是不可逆的。但是网上由一些破解软件
//salt:盐
Md5Hash md5Hash1=new Md5Hash("123456","abc?!");
System.out.println(md5Hash1);
//设置n次加密
Md5Hash md5Hash2 = new Md5Hash("123456","abc?!",1024);
}
}
9.1 shiro使用密码加密器
修改realm代码
10.自定义realm的授权功能
package com.yk.demo03;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthenticatingRealm;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.util.ByteSource;
import java.util.List;
public class MyRealm extends AuthorizingRealm {
private UserService userService = new UserService();
//什么时候执行该方法: 当你进行权限校验时会执行该方法
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
User user = (User) principalCollection.getPrimaryPrincipal();
//根据账号查询该用户具有哪些权限
List<String> list= userService.findPermissionByUsername(user.getUsername());
if(list!=null&&list.size()>0){
SimpleAuthorizationInfo info=new SimpleAuthorizationInfo();
info.addStringPermissions(list);
return info;
}
return null;
}
//
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
//1.根据token获取账号
String username = (String) authenticationToken.getPrincipal();
//2.根据账号查询用户信息
User user = userService.findByUsername(username);
if(user!=null){
//从数据库中获取的密码
ByteSource credentialsSalt=ByteSource.Util.bytes(user.getSalt());
SimpleAuthenticationInfo info = new SimpleAuthenticationInfo(user,user.getPassword(),credentialsSalt,this.getName());
return info;
}
return null;
}
}
测试:
package com.yk.demo03;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.authc.credential.HashedCredentialsMatcher;
import org.apache.shiro.mgt.DefaultSecurityManager;
import org.apache.shiro.subject.Subject;
public class TestShiro04 {
public static void main(String[] args) {
DefaultSecurityManager securityManager=new DefaultSecurityManager();
MyRealm myRealm=new MyRealm();
HashedCredentialsMatcher credentialsMatcher = new HashedCredentialsMatcher();
credentialsMatcher.setHashAlgorithmName("MD5");
credentialsMatcher.setHashIterations(1024);
myRealm.setCredentialsMatcher(credentialsMatcher);
securityManager.setRealm(myRealm);
SecurityUtils.setSecurityManager(securityManager);
Subject subject = SecurityUtils.getSubject();
try {
UsernamePasswordToken token = new UsernamePasswordToken("ykq", "123456");
subject.login(token);
System.out.println(subject.isPermitted("user:query"));
System.out.println(subject.isPermitted("user:update"));
}catch (Exception e){
System.out.println("账号密码错误");
}
}
}