1.什么是权限管理?
只要有用户参与的系统一般都要有权限管理,权限管理实现对用户访问系统的控制,按照安全规则或者安全策略控制用户可以访问而且只能访问自己被授权的资源。
对权限的管理又分为两大类别:
- 用户认证
- 用户授权
1.1 用户认证
用户认证,用户去访问系统,系统要验证用户身份的合法性
最常用的用户身份验证的方法:1、用户名密码方式、2、指纹打卡机、3、基于证书验证方法。。系统验证用户身份合法之后,用户方可访问系统的资源
用户认证的流程:
- 判断该资源能否不认证就能访问【登陆页面、首页】
- 如果该资源需要认证后才能访问,那么判断该访问者是否认证了
- 如果还没有认证,那么需要返回到【登陆页面】,用户输入认证信息后 进行认证
- 认证通过后才能访问资源
从用户认证中可以抽取出这么几个概念(术语)
- subject主体:理解为用户,可能是程序(比如navicat去连接数据库),都要去访问系统的资源,系统需要对subject进行身份认证 通俗的讲为当前用户
- principal身份信息:通常是唯一的,一个主体还有多个身份信息,但是都有一个主身份信息(primary principal)【我们可以选择身份证认证、学生证认证等等都是我们的身份信息】 —》当前用户的账号**
- credential凭证信息:可以是密码 、证书、指纹。 --------》密码
总结:主体在进行身份认证时需要提供身份信息和凭证信息。
1.2 用户授权
用户授权,简单理解为访问控制,在用户认证通过后,系统对用户访问资源进行控制,用户具有资源的访问权限才可以访问。
用户授权的流程
- 用户认证通过后 ,到达了用户授权环节
- 用户访问资源,系统需要判断该用户是否有权限去操作该资源
- 有权限才能够访问,有权限就不能访问了 401(认证失败),403(无权限)
授权的过程可以简单理解为:主体认证之后,系统进行访问控制,subject必须具备资源的访问权限才可访问该资源…
2 什么是shiro?
shiro是一个功能强大、易于使用的Java安全框架,可以执行身份验证,授权、加密和会话管理。通过Shiro易于理解的API,您可以做到这一点快速、轻松地保护任何应用程序——从最小的移动应用程序到最大的we和企业应用程序。
2.1 shiro架构?
Subject:主体,代表了当前 “用户”,这个用户不一定是一个具体的人,与当前应用交互的任何东西都是 Subject,如网络爬虫,机器人等;即一个抽象概念;所有 Subject 都绑定到 SecurityManager,与 Subject 的所有交互都会委托给 SecurityManager;可以把 Subject 认为是一个门面;SecurityManager 才是实际的执行者;
SecurityManager:安全管理器;即所有与安全有关的操作都会与 SecurityManager 交互;且它管理着所有 Subject;可以看出它是 Shiro 的核心,它负责与后边介绍的其他组件进行交互,如果学习过 SpringMVC,你可以把它看成 DispatcherServlet 前端控制器;
Realm:域,Shiro 从从 Realm 获取安全数据(如用户、角色、权限),就是说 SecurityManager 要验证用户身份,那么它需要从 Realm 获取相应的用户进行比较以确定用户身份是否合法;也需要从 Realm 得到用户相应的角色 / 权限进行验证用户是否能进行操作;可以把 Realm 看成 DataSource,即安全数据源。
2.2 shiro的认证
1.新建maven工程导入以下依赖
<dependencies>
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-core</artifactId>
<version>1.4.1</version>
</dependency>
<!-- configure logging -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>jcl-over-slf4j</artifactId>
<version>1.7.21</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>1.7.21</version>
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>
</dependencies>
shoiro使用
1.第一步:先配置pom.xml 的架包
2.第二步:创建一个ini文件,在resources目录下
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-pN0cfErD-1593435761898)(C:\Users\常光华\AppData\Roaming\Typora\typora-user-images\image-20200628201346681.png)]
2.1: 第一种方法:在ini文件 写死的两个用户
#配置用户 在[users] 标志下写 用户名=密码,角色 将用户和角色进行绑定
[users]
root=123456,admin
xiaola=123456,manager
#配置角色 *表示拥有所有权限
#角色=资源:操作权限
[roles]
admin=*
manager=goods:add,goods:update,goods:delete
role1=goods:add
2.2:在test文件下写上
package com.aaa.shiro.test;
import com.sun.org.omg.CORBA.InitializerSeqHelper;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.config.IniSecurityManagerFactory;
import org.apache.shiro.mgt.SecurityManager;
import org.apache.shiro.subject.Subject;
/**
* @AUTHOR (常光华)
* @date 2020-06-28 16:38
*/
public class ShiroStart {
public static void main(String[] args) {
//1.加载shiro 配置文件
IniSecurityManagerFactory iniSecurityManagerFactory=new IniSecurityManagerFactory("classpath:shiro.ini");
//2.得到securityManager管理器
SecurityManager securityManager=iniSecurityManagerFactory.getInstance();
//3.讲当前应用 和 安全管理器进行绑定
SecurityUtils.setSecurityManager(securityManager);
//获取当前用户
Subject currentUser =SecurityUtils.getSubject();
//判断当前用户是否已经认证
if (!currentUser.isAuthenticated()){
UsernamePasswordToken token=new UsernamePasswordToken("xiaola","123456");
//去认证
currentUser.login(token);
if (currentUser.hasRole("manager")){
System.out.println("当前用户拥有经理角色");
}
if (currentUser.isPermitted("goods:add")){
System.out.println("当前用户拥有添加商品的权限");
}
if (currentUser.isPermitted("goods:get")){
System.out.println("当前用户没有获取商品的权限");
}
//获取认证的用户名
String username= (String) currentUser.getPrincipal();
System.out.println("username:"+username);
//退出登录 ,让当前的认证失效
currentUser.logout();
//再次验证
username= (String) currentUser.getPrincipal();
System.out.println("username:"+username);
}
}
}
方法二:
1现在ini文件中写上路径
[main]
myRealm=com.aaa.shiro.test.CustomerRealm1
2.创建CustomerRealm1类
package com.aaa.shiro.test;
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;
/**
* @AUTHOR (常光华)
* @date 2020-06-28 19:09
*/
public class CustomerRealm1 extends AuthenticatingRealm {
//认证
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
String username= (String) authenticationToken.getPrincipal();
//假装去数据库找到 username 对应的密码
String password="123456";
SimpleAuthenticationInfo authenticationInfo = new SimpleAuthenticationInfo(username, password, this.getName());
return authenticationInfo;
}
}
3.最后测试:
package com.aaa.shiro.test;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.*;
import org.apache.shiro.config.IniSecurityManagerFactory;
import org.apache.shiro.mgt.SecurityManager;
import org.apache.shiro.subject.Subject;
/**
* @AUTHOR (常光华)
* @date 2020-06-28 19:28
*/
public class ShiroStart1 {
public static void main(String[] args) {
//1.加载shiro 配置文件
IniSecurityManagerFactory iniSecurityManagerFactory=
new IniSecurityManagerFactory("classpath:shiro1.ini");
//2.得到管理器
SecurityManager securityManager=iniSecurityManagerFactory.getInstance();
//3.讲当前应用 和 安全管理器进行绑定
SecurityUtils.setSecurityManager(securityManager);
//获取当前用户
Subject currentUser=SecurityUtils.getSubject();
//判断当前用户是否已经认证
if (!currentUser.isAuthenticated()){
UsernamePasswordToken token=new UsernamePasswordToken("rootdf","123456");
try {
currentUser.login(token);
} catch (UnknownAccountException uae) {
// 找不到用户名
System.out.println("There is no user with username of " + token.getPrincipal());
} catch (IncorrectCredentialsException ice) {
// 密码错误
System.out.println("Password for account " + token.getPrincipal() + " was incorrect!");
} catch (LockedAccountException lae) {
// 用户已被锁定
System.out.println("The account for username " + token.getPrincipal() + " is locked. " +
"Please contact your administrator to unlock it.");
}
// ... catch more exceptions here (maybe custom ones specific to your application?
catch (AuthenticationException ae) {
//unexpected condition? error?
System.out.println("其他异常");
}
if ( currentUser.isAuthenticated()){
System.out.println("认证成功");
}
if (currentUser.hasRole("manager")){
System.out.println("当前用户拥有经理角色");
}
if (currentUser.isPermitted("goods:add")){
System.out.println("当前用户拥有添加商品的权限");
}
if (currentUser.isPermitted("goods:get")){
System.out.println("当前用户没有获取商品的权限");
}
// 获取认证的用户名
String username = (String) currentUser.getPrincipal();
System.out.println("username:"+username);
// 退出登陆 ,让当前的认真失效
currentUser.logout();
// 再次验证
username = (String) currentUser.getPrincipal();
System.out.println("username:"+username);
}
}
}
同理和第二种方法一样的写法:
第一步:
[main]
myRealm=com.aaa.shiro.test.CustomerRealm2
第二步:
package com.aaa.shiro.test;
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.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
/**
* @AUTHOR (常光华)
* @date 2020-06-28 19:46
*/
public class CustomerRealm2 extends AuthorizingRealm {
//授权
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
String username= (String) principalCollection.getPrimaryPrincipal();
SimpleAuthorizationInfo simpleAuthorizationInfo = new SimpleAuthorizationInfo();
if (username.equals("root")){
//根据用户 去数据库拿 对应角色和权限
simpleAuthorizationInfo.addRole("admin");
simpleAuthorizationInfo.addRole("manager");
simpleAuthorizationInfo.addStringPermission("goods:add");
simpleAuthorizationInfo.addStringPermission("goods:delete");
simpleAuthorizationInfo.addStringPermission("goods:get");
}
return simpleAuthorizationInfo;
}
//认证
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
String username = (String) authenticationToken.getPrincipal();
//假装去数据找到 username 对应的密码
String password="123456";
SimpleAuthenticationInfo authenticationInfo=new SimpleAuthenticationInfo(username,password,this.getName());
return authenticationInfo;
}
}
第三步:
package com.aaa.shiro.test;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.*;
import org.apache.shiro.config.IniSecurityManagerFactory;
import org.apache.shiro.mgt.SecurityManager;
import org.apache.shiro.subject.Subject;
/**
* @AUTHOR (常光华)
* @date 2020-06-28 19:59
*/
public class ShiroStart2 {
public static void main(String[] args) {
//1.加载shiro配置文件
IniSecurityManagerFactory iniSecurityManagerFactory=
new IniSecurityManagerFactory("classpath:shiro2.ini");
//2.得到securityManager 管理器
SecurityManager securityManager = iniSecurityManagerFactory.getInstance();
//3.将当前应用 和 安全管理器进行绑定
SecurityUtils.setSecurityManager(securityManager);
//获取当前用户
Subject currentUser=SecurityUtils.getSubject();
// 判断当前用户是否已经认证
if (!currentUser.isAuthenticated()){
UsernamePasswordToken token = new UsernamePasswordToken("root","123456");
try {
//去认证
currentUser.login(token);
} catch (UnknownAccountException uae) {
// 找不到用户名 token.getPrincipal()
System.out.println("There is no user with username of " + token.getPrincipal());
} catch (IncorrectCredentialsException ice) {
// 密码错误
System.out.println("Password for account " + token.getPrincipal() + " was incorrect!");
} catch (LockedAccountException lae) {
// 用户已被锁定
System.out.println("The account for username " + token.getPrincipal() + " is locked. " +
"Please contact your administrator to unlock it.");
}
// ... catch more exceptions here (maybe custom ones specific to your application?
catch (AuthenticationException ae) {
//unexpected condition? error?
System.out.println("其他异常");
}
if ( currentUser.isAuthenticated()){
System.out.println("认证成功");
}
if (currentUser.hasRole("manager")){
System.out.println("当前用户拥有经理角色");
}
if (currentUser.isPermitted("goods:add")){
System.out.println("当前用户拥有添加商品的权限");
}
if (currentUser.isPermitted("goods:get")){
System.out.println("当前用户没有获取商品的权限");
}
// 获取认证的用户名
String username = (String) currentUser.getPrincipal();
System.out.println("username:"+username);
// 退出登陆 ,让当前的认真失效
currentUser.logout();
// 再次验证
username = (String) currentUser.getPrincipal();
System.out.println("username:"+username);
}
}
}
if (currentUser.isPermitted("goods:get")){
System.out.println("当前用户没有获取商品的权限");
}
// 获取认证的用户名
String username = (String) currentUser.getPrincipal();
System.out.println("username:"+username);
// 退出登陆 ,让当前的认真失效
currentUser.logout();
// 再次验证
username = (String) currentUser.getPrincipal();
System.out.println("username:"+username);
}
}
}