Shiro学习之Shiro基本使用(2)

简介: Shiro学习之Shiro基本使用(2)

1.0 Shiro学习之Shiro基本使用

1.1 角色、授权

1、授权概念

(1)授权,也叫访问控制,即在应用中控制谁访问哪些资源(如访问页面/编辑数据/页面操作 等)。在授权中需了解的几个关键对象

:主体(Subject)、资源(Resource)、权限 (Permission)、角(Role)。

(2)主体(Subject):访问应用的用户,在 Shiro 中使用 Subject 代表该用户。用户只有授权 后才允许访问相应的资源。

(3)资源(Resource):在应用中用户可以访问的 URL,比如访问 JSP 页面、查看/编辑某些 数据、访问某个业务方法、打印文本等等都是资源。用户只要授权后才能访问。

(4)权限(Permission):安全策略中的原子授权单位,通过权限我们可以表示在应用中用户 有没有操作某个资源的权力。即权限表示在应用中用户能不能访问某个资源,如:访问用 户列表页面查看/新增/修改/删除用户数据(即很多时候都是CRUD(增查改删)式权限控 制)等。权限代表了用户有没有操作某个资源的权利,即反映在某个资源上的操作允不允 许。

(5)Shiro 支持粗粒度权限(如用户模块的所有权限)和细粒度权限(操作某个用户的权限, 即实例级别的)

(6)角色(Role):权限的集合,一般情况下会赋予用户角色而不是权限,即这样用户可

以拥有 一组权限,赋予权限时比较方便。典型的如:项目经理、技术总监、CTO、开发工

程师等 都是角色,不同的角色拥有一组不同的权限

2、授权方式

(1)编程式:通过写if/else 授权代码块完成

(2)注解式:通过在执行的Java方法上放置相应的注解完成,没有权限将抛出相 应的异常

(3)JSP/GSP 标签:在JSP/GSP 页面通过相应的标签完成

3、授权流程

(1)首先调用Subject.isPermitted*/hasRole*接口,其会委托给SecurityManager,而

SecurityManager接着会委托给 Authorizer;

(2)Authorizer是真正的授权者,如果调用如isPermitted(“user:view”),其首先会通

过PermissionResolver把字符串转换成相应的Permission实例;

(3)在进行授权之前,其会调用相应的Realm获取Subject相应的角色/权限用于匹配传入

的角色/权限;

(4)Authorizer会判断Realm的角色/权限是否和传入的匹配,如果有多个Realm,会委托

给ModularRealmAuthorizer进行循环判断,如果匹配如isPermitted*/hasRole* 会返回

true,否则返回false表示授权失败

4、授权实例

(1)获取角色信息

shiro.ini

[users]
zhangsan=z3,role1,role2
lisi=l4

(2)、给例子添加代码,沟通过hasRole()判断用户是否有指定角色

部分代码:

//5.判断是否有角色(我们刚在shiro.ini添加的)
            boolean hasRole = subject.hasRole("role1");
            System.out.println("是否拥有此角色"+hasRole);

全量代码

package com.yanwc.shirotest;
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;
public class ShiroRun {
    public static void main(String[] args) {
        //1.获取初始化Securitymanager 登录管理器
        //获取配置文件中我们假设的账号和密码得到值
        IniSecurityManagerFactory factory = new IniSecurityManagerFactory("classpath:shiro.ini");
        //获取其中对象的值
        SecurityManager securityManager = factory.getInstance();
        //借助工具SecurityUtils
        SecurityUtils.setSecurityManager(securityManager);
        // 2.获取Subject对象
        Subject subject = SecurityUtils.getSubject();
        //3.创建token对象 web应用用户名密码从页面传递
        AuthenticationToken token = new UsernamePasswordToken("zhangsan", "z3");
         //4 完成登录
        try {
            subject.login(token);
            System.out.println("登录成功");
            //5.判断是否有角色(我们刚在shiro.ini添加的)
            boolean hasRole = subject.hasRole("role1");
            System.out.println("是否拥有此角色"+hasRole);
        } catch (UnknownAccountException e) {
            e.printStackTrace();
            System.out.println("用户不存在");
        } catch (IncorrectCredentialsException e) {
            e.printStackTrace();
            System.out.println("密码错误");
        } catch (AuthenticationException ae) {
            //unexpected condition? error?
        }
    }
}

(3)判断权限信息信息

1、给shiro.ini增加权限配置
[roles]
role1=user:insert,user:select

2、给例子添加代码,判断用户是否有指定权限

部分代码

//6. 是否拥有此权限
            boolean permitted = subject.isPermitted("user:insert");
            System.out.println("是否拥有此权限"+permitted);
            //也可以用 checkPermission 方法,但没有返回值,没权限抛 AuthenticationException
            subject.checkPermission("user:select");

全量代码

package com.yanwc.shirotest;
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;
public class ShiroRun {
    public static void main(String[] args) {
        //1.获取初始化Securitymanager 登录管理器
        //获取配置文件中我们假设的账号和密码得到值
        IniSecurityManagerFactory factory = new IniSecurityManagerFactory("classpath:shiro.ini");
        //获取其中对象的值
        SecurityManager securityManager = factory.getInstance();
        //借助工具SecurityUtils
        SecurityUtils.setSecurityManager(securityManager);
        // 2.获取Subject对象
        Subject subject = SecurityUtils.getSubject();
        //3.创建token对象 web应用用户名密码从页面传递
        AuthenticationToken token = new UsernamePasswordToken("zhangsan", "z3");
         //4 完成登录
        try {
            subject.login(token);
            System.out.println("登录成功");
            //5.判断是否有角色(我们刚在shiro.ini添加的)
            boolean hasRole = subject.hasRole("role1");
            System.out.println("是否拥有此角色"+hasRole);
            //6. 是否拥有此权限
            boolean permitted = subject.isPermitted("user:insert");
            System.out.println("是否拥有此权限"+permitted);
            //也可以用 checkPermission 方法,但没有返回值,没权限抛 AuthenticationException
            subject.checkPermission("user:select");
        } catch (UnknownAccountException e) {
            e.printStackTrace();
            System.out.println("用户不存在");
        } catch (IncorrectCredentialsException e) {
            e.printStackTrace();
            System.out.println("密码错误");
        } catch (AuthenticationException ae) {
            //unexpected condition? error?
        }
    }
}

1.2 Shiro 加密

实际系统开发中,一些敏感信息需要进行加密,比如说用户的密码。Shiro 内嵌很多常用的加密算法,比如 MD5 加密。Shiro 可以很简单的使用信息加密。

1、使用Shiro进行密码加密

新建ShiroMD5 测试;

package com.yanwc.shirotest;
import org.apache.shiro.crypto.hash.Md5Hash;
import org.apache.shiro.crypto.hash.SimpleHash;
public class ShiroMD5 {
    public static void main(String[] args) {
        //1.密文密码  .toHex()  =》将md5值转为16进制便于查看
        String password = "z3";
        //使用MD5进行加密
        Md5Hash md5Hash = new Md5Hash(password);
        System.out.println("使用md5加密的明文=" + md5Hash.toHex());
        //2.带盐的MD5加密,盐加密就是再密码明文的后面拼接新字符串再进行加密
        //salt  加盐参数
        Md5Hash md5Hash1 = new Md5Hash(password, "salt");
        System.out.println("带盐的MD5加密=" + md5Hash1.toHex());
        //3.为了确保数据的安全性,避免被破解可以采用迭代多次加密保证数据的安全
        //数字3 代表了加密的次数为3(MD5)
        Md5Hash md5Hash2 = new Md5Hash(password, "salt", 3);
        System.out.println("带盐的MD5加密3次加密=" + md5Hash2.toHex());
       //4.使用父类进行过加密 md5是继承SimpleHash 我们来使用他加密
        //参数介绍: 1.MD5 加密得到方式 2.需要加密的密码 3. 字符串拼接 4. 3 加密次数
        SimpleHash simpleHash=new SimpleHash("MD5",password,"salt",3);
        System.out.println("使用父类的带盐的MD5加密3次加密=" + simpleHash.toHex());
    }
}

执行结果:

使用md5加密的明文=a61d1457beb4684e254ce60379c8ae7b
带盐的MD5加密=dd4611daf1e40eff99b9fdcadbd22674
带盐的MD5加密3次加密=7174f64b13022acd3c56e2781e098a5f
使用父类的带盐的MD5加密3次加密=7174f64b13022acd3c56e2781e098a5f

1.3 Shiro 自定义登录认证

Shiro 默认的登录认证是不带加密的,如果想要实现加密认证需要自定义登录认证,自定义 Realm。

1、自定义登录认证

(类比较多一一说明下,有问题直接复制我的代码)

(如果还有不明白请留言一一解答)

1.1MyRealm

package com.yanwc.shirotest;
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;
import org.apache.shiro.util.ByteSource;
public class MyRealm extends AuthenticatingRealm {
    //TODO 自定义登录认证的方法
    //1. shiro的login方法底层会调用该类的认证方法进行认证
    //2.需要配置的自定的realm生效,在shiro.ini中配置(模拟)也可以在springboot中配置
    //3.该方法只是获取进行对比的信息,认证的逻辑还是按照shiro底层认证的逻辑进行完成
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
        //1.获取身份信息
        String principal = authenticationToken.getPrincipal().toString();
        //2.获取凭证信息
        String password = new String((char[]) authenticationToken.getCredentials());
        System.out.println("认证用户信息"+principal+"---"+password);
        //3 获取数据库中存储的用户信息(模拟)
        if(principal.equals("zhangsan")){
            //3.1 数据库存储的加盐迭代 3 次密码
            String pwdInfo = "7174f64b13022acd3c56e2781e098a5f";
            //3.2 创建封装了校验逻辑的对象,将要比较的数据给该对象
            //参数 1.获取身份信息  2.密码信息(加密后的密码)  3.加密拼接字符串
            // 4.获取身份信息的字符串
            AuthenticationInfo info = new SimpleAuthenticationInfo(
                    authenticationToken.getPrincipal(),
                    pwdInfo,
                    ByteSource.Util.bytes("salt"),
                    authenticationToken.getPrincipal().toString());
            return info;
        }
        return null;
    }
}

ShiroMD5

package com.yanwc.shirotest;
import org.apache.shiro.crypto.hash.Md5Hash;
import org.apache.shiro.crypto.hash.SimpleHash;
public class ShiroMD5 {
    public static void main(String[] args) {
        //1.密文密码  .toHex()  =》将md5值转为16进制便于查看
        String password = "z3";
        //使用MD5进行加密
        Md5Hash md5Hash = new Md5Hash(password);
        System.out.println("使用md5加密的明文=" + md5Hash.toHex());
        //2.带盐的MD5加密,盐加密就是再密码明文的后面拼接新字符串再进行加密
        //salt  加盐参数
        Md5Hash md5Hash1 = new Md5Hash(password, "salt");
        System.out.println("带盐的MD5加密=" + md5Hash1.toHex());
        //3.为了确保数据的安全性,避免被破解可以采用迭代多次加密保证数据的安全
        //数字3 代表了加密的次数为3(MD5)
        Md5Hash md5Hash2 = new Md5Hash(password, "salt", 3);
        System.out.println("带盐的MD5加密3次加密=" + md5Hash2.toHex());
       //4.使用父类进行过加密 md5是继承SimpleHash 我们来使用他加密
        //参数介绍: 1.MD5 加密得到方式 2.需要加密的密码 3. 字符串拼接 4. 3 加密次数
        SimpleHash simpleHash=new SimpleHash("MD5",password,"salt",3);
        System.out.println("使用父类的带盐的MD5加密3次加密=" + simpleHash.toHex());
    }
}

ShiroRun

package com.yanwc.shirotest;
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;
public class ShiroRun {
    public static void main(String[] args) {
        //1.获取初始化Securitymanager 登录管理器
        //获取配置文件中我们假设的账号和密码得到值
        IniSecurityManagerFactory factory = new IniSecurityManagerFactory("classpath:shiro.ini");
        //获取其中对象的值
        SecurityManager securityManager = factory.getInstance();
        //借助工具SecurityUtils
        SecurityUtils.setSecurityManager(securityManager);
        // 2.获取Subject对象
        Subject subject = SecurityUtils.getSubject();
        //3.创建token对象 web应用用户名密码从页面传递
        AuthenticationToken token = new UsernamePasswordToken("zhangsan", "z3");
         //4 完成登录
        try {
            subject.login(token);
            System.out.println("登录成功");
            //5.判断是否有角色(我们刚在shiro.ini添加的)
            boolean hasRole = subject.hasRole("role1");
            System.out.println("是否拥有此角色"+hasRole);
            //6. 是否拥有此权限
            boolean permitted = subject.isPermitted("user:insert");
            System.out.println("是否拥有此权限"+permitted);
            //也可以用 checkPermission 方法,但没有返回值,没权限抛 AuthenticationException
            subject.checkPermission("user:select");
        } catch (UnknownAccountException e) {
            e.printStackTrace();
            System.out.println("用户不存在");
        } catch (IncorrectCredentialsException e) {
            e.printStackTrace();
            System.out.println("密码错误");
        } catch (AuthenticationException ae) {
            //unexpected condition? error?
        }
    }
}

shiro.ini 配置类(模拟数据库)

[main]
#MD5加密 加密次数3
md5CredentialsMatcher=org.apache.shiro.authc.credential.Md5CredentialsMatcher
md5CredentialsMatcher.hashIterations=3
#指定底层调用路径
myrealm=com.yanwc.shirotest.MyRealm
myrealm.credentialsMatcher=$md5CredentialsMatcher
#指定本地类
securityManager.realms=$myrealm
[users]
zhangsan=7174f64b13022acd3c56e2781e098a5f,role1,role2
lisi=l4
[roles]
role1=user:insert,user:select

pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <parent>
        <artifactId>shirodemotest</artifactId>
        <groupId>org.example</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>
    <dependencies>
        <dependency>
            <groupId>org.apache.shiro</groupId>
            <artifactId>shiro-core</artifactId>
            <version>1.9.0</version>
        </dependency>
        <dependency>
            <groupId>commons-logging</groupId>
            <artifactId>commons-logging</artifactId>
            <version>1.2</version>
        </dependency>
    </dependencies>
    <artifactId>shiro_login</artifactId>
    <properties>
        <maven.compiler.source>8</maven.compiler.source>
        <maven.compiler.target>8</maven.compiler.target>
    </properties>
</project>


相关文章
fdfs文件上传开机重启后ERRORserver:192.168.1.22:22122,response.status.28!=0以及2!=0
fdfs文件上传开机重启后ERRORserver:192.168.1.22:22122,response.status.28!=0以及2!=0
315 0
|
搜索推荐 IDE 开发工具
IDEA自定义右键菜单
IDEA自定义右键菜单
2842 1
|
XML 存储 SQL
独立部署Xray反练平台——详细说明加举例xxe漏洞
xray 是一款功能强大的安全评估工具,由多名经验丰富的一线安全从业者呕心打造而成,主要特性有:检测速度快。发包速度快; 漏洞检测算法高效。支持范围广。大至 OWASP Top 10 通用漏洞检测,小至各种 CMS 框架 POC,均可以支持。代码质量高。编写代码的人员素质高, 通过 Code Review、单元测试、集成测试等多层验证来提高代码可靠性。高级可定制。通过配置文件暴露了引擎的各种参数,通过修改配置文件可以极大的客制化功能。安全无威胁。xray 定位为一款安全辅助评估工具,而不是攻击工具,内置的所有 payload 和 poc 均为无害化检查。
2018 0
独立部署Xray反练平台——详细说明加举例xxe漏洞
ThreeJs绘制贝塞尔曲线
这篇文章介绍了如何利用Three.js绘制贝塞尔曲线,并提供了实现的代码示例与说明。
205 2
ThreeJs绘制贝塞尔曲线
|
存储 安全 Java
shiro学习二:shiro的加密认证详解,加盐与不加盐两个版本。
这篇文章详细介绍了Apache Shiro安全框架中密码的加密认证机制,包括不加盐和加盐两种加密方式的实现和测试。
757 0
|
运维 Linux Apache
Docker详解(十二)——Docker容器权限问题
Docker详解(十二)——Docker容器权限问题
3699 5
|
存储 机器学习/深度学习 安全
|
移动开发 安全 前端开发
技术笔记:robocopy复制文件(转载)
技术笔记:robocopy复制文件(转载)
619 0
|
存储 缓存 数据库
Shiro【核心功能、核心组件、项目搭建 、配置文件认证、数据库认证 】(一)-全面详解(学习总结---从入门到深化)
Shiro【核心功能、核心组件、项目搭建 、配置文件认证、数据库认证 】(一)-全面详解(学习总结---从入门到深化)
631 1
|
存储 缓存 安全
Shiro-全面详解(学习总结---从入门到深化)(上)
Shiro是apache旗下的一个开源安全框架,它可以帮助我们完成身 份认证,授权、加密、会话管理等功能。
562 0
Shiro-全面详解(学习总结---从入门到深化)(上)