【Java】一文带你快速入门Shiro权限框架

这篇具有很好参考价值的文章主要介绍了【Java】一文带你快速入门Shiro权限框架。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

🚀Java中权限控制框架-Shiro

📓推荐网站(不断完善中):个人博客

📌个人主页:个人主页

👉相关专栏:CSDN专栏

🏝立志赚钱,干活想躺,瞎分享的摸鱼工程师一枚

【Java】一文带你快速入门Shiro权限框架

🏖前言

在我们实战开发过程中,对于权限的控制是必不可少的,一个系统中常见的有普通会员、管理员、超级管理员等等不同的角色出现。

我们如何更优雅的在Java中使用权限框架?来看看Java中比较火热的权限框架之一shiro吧~

1.简介

1.1.什么是Shiro

​ Shiro是apache旗下一个开源框架,它将软件系统的安全认证相关的功能抽取出来,实现用户身份认证,权限授权、加密、会话管理等功能,组成了一个通用的安全认证框架。

​ 使用shiro可以非常快速的完成认证、授权等功能的开发,降低系统成本。

官方地址

1.2.Shiro功能简介

shiro中的三大核心组建:Subject、SecurityManager、Realm

  • Subject:代表了当前用户的安全操作(也就是该接口中定义了许多与授权认证相关的方法)
  • SecurityManager:它是Shiro框架的核心,Shiro通过SecurityManager来管理内部组件实例,并通过它来提供安全管理的各种服务。
  • Realm:Realm充当了Shiro与应用安全数据间的“桥梁”或者“连接器”。也就是说,当对用户执行认证(登录)和授权(访问控制)验证时,Shiro会从应用配置的Realm中查找用户及其权限信息

其他常见功能组件

Authentication身份认证/登录,验证用户是不是拥有相应的身份

Authorization授权,即权限验证,验证某个已认证的用户是否拥有某个权限;即判断用 户是否能进行什么操作,如:验证某个用户是否拥有某个角色。或者细粒度的验证某个用户对某个资源是否具有某个权限;

SessionManager:SessionManager即会话管理,shiro框架定义了一套会话管理,它不依赖web容器的session,所以shiro可以使用在非web应用上,也可以将分布式应用的会话集中在一点管理,此特性可使它实现单点登录。

SessionDao:SessionDAO即会话dao,是对session会话操作的一套接口,比如要将会话信息存储到redis数据库

CacheManager:CacheManager即缓存管理,将用户权限数据存储在缓存,这样可以提高性能

Cryptography:即密码管理,shiro提供了一套加密/解密的组件,方便开发。比如提供常用的散列、加/解密等功能

1.3.Shiro架构图

【Java】一文带你快速入门Shiro权限框架

2.关于权限控制

2.1.权限逻辑

权限管理的范围应该是怎么样的?

​ 基本上涉及到用户参与的系统都要进行权限管理,权限管理属于系统安全的范畴,权限管理实现对用户访问系统的控制,按照安全规则或者安全策略控制用户可以访问而且只能访问自己被授权的资源

​ 权限管理包括身份认证和授权两部分,简称认证授权。对于需要访问控制的资源用户首先经过身份认证,认证通过后用户具有该资源的访问权限方可访问

关于认证:身份认证,就是判断一个用户是否为合法用户的处理过程

权限认证流程图

【Java】一文带你快速入门Shiro权限框架

2.2.权限模型

在权限中无非就这么几个概念内容为:主体、资源、权限(Permission)

  • 主体:访问资源者
  • 资源:各种信息
  • 权限:规定主体对资源的访问权

模型图

【Java】一文带你快速入门Shiro权限框架

主体(账号、密码)、 资源(资源名称、访问地址)、权限(权限名称、资源id)、 角色(角色名称)

角色和权限关系(角色id、权限id)、 主体和角色关系(主体id、角色id)

实际开发常见模型图

​ 实际企业开发中会将资源与权限表合为一张表

​ 资源(资源名称、访问地址) 权限(权限名称、资源id)合并为:资源(权限名称、资源名称、资源访问地址)

【Java】一文带你快速入门Shiro权限框架

2.2.1.权限解决方案

对资源类型的管理称为粗颗粒度权限管理,即只控制到菜单、按钮、方法等

​ 例如:用户具有用户管理的权限,具有导出订单明细的权限

对资源实例的控制称为细颗粒度权限管理,即控制到数据级别的权限

​ 例如:用户只允许修改本部门的员工信息,用户只允许导出自己创建的订单明细

对于粗颗粒度的权限管理可以很容易做系统架构级别的功能,即系统功能操作使用统一的粗颗粒度的权限管理。

对于细颗粒度的权限管理不建议做成系统架构级别的功能,因为对数据级别的控制是系统的业务需求,随着业务需求的变更业务功能变化的可能性很大,建议对数据级别的权限控制在业务层个性化开发,

​ 例如:用户只允许修改自己创建的商品信息可以在service接口添加校验实现,service接口需要传入当前操作人的标识,与商品信息创建人标识对比,不一致则不允许修改商品信息

2.3.URL权限拦截

基于url拦截是企业中常用的权限管理方法,实现思路是:将系统操作的每个url配置在权限表中,将权限对应到角色,将角色分配给用户,用户访问系统功能通过Filter进行过虑,过虑器获取到用户访问的url,只要访问的url是用户分配角色中的url则放行继续访问

【Java】一文带你快速入门Shiro权限框架

3.简单入门

3.1.环境搭建

pom.xml文件

<dependencies>
    <dependency>
        <groupId>commons-logging</groupId>
        <artifactId>commons-logging</artifactId>
        <version>1.2</version>
    </dependency>

    <!-- junit start -->
    <dependency>
        <groupId>junit</groupId>
        <artifactId>junit</artifactId>
        <version>4.12</version>
        <scope>test</scope>
    </dependency>

    <dependency>
        <groupId>org.apache.shiro</groupId>
        <artifactId>shiro-core</artifactId>
        <version>1.3.2</version>
    </dependency>
</dependencies>

日志配置

log4j.rootLogger=debug,console
log4j.appender.console=org.apache.log4j.ConsoleAppender
log4j.appender.console.layout=org.apache.log4j.PatternLayout
log4j.appender.console.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss}  [%p] %c %m %n

shiro.ini配置

​ shiro.ini是shiro默认可以识别的配置文件,将与权限相关的内容写在shiro.ini文件中可以直接被加载

​ 通过shiro.ini配置文件初始化SecurityManager环境

[users]
zhangsan=123456,admin
lisi=654321,superadmin

[roles]
admin=product:create,product:update,product:delete
superadmin=product:create,product:update,product:delete,user:delete

3.2.实战

3.2.1.实战流程

构建一个SecurityManager环境的流程

  1. 初始化一个SecurityManager(安全管理器)对象
    • 通过shiro.ini文件初始化一个SecurityManager工厂
    • 通过工厂获取SecurityManager(安全管理器)
  2. 使用SecurityUtils将securityManager设置到运行环境中
  3. 创建一个Subject实例,securityManager会管理该主体
  4. 创建token令牌,记录用户认证的身份和凭证即账号和密码
  5. 认证
3.2.2.实战测试
@Test
public void shiro(){
    //通过shiro.ini初始化一个SecurityManager工厂
    IniSecurityManagerFactory iniSecurityManagerFactory=new IniSecurityManagerFactory("classpath:shiro.ini");
    //通过工厂获取一个SecurityManager管理器
    SecurityManager securityManager = iniSecurityManagerFactory.getInstance();
    //使用SecurityUtils将securityManager设置到运行环境中
    SecurityUtils.setSecurityManager(securityManager);
    //创建一个Subject实例
    Subject subject = SecurityUtils.getSubject();
    //创建token令牌,记录用户登陆的身份和凭证即账号密码
    UsernamePasswordToken user = new UsernamePasswordToken("zhangsan", "123456");
    //登陆认证(如果认证不通过回抛异常)
    subject.login(user);
    //查询认证状态
    System.out.println(subject.isAuthenticated());
    //查询用户的授权信息
    System.out.println("是否有删除用户的权限" + subject.isPermitted("user:delete"));
    System.out.println("是否有添加产品的权限" + subject.isPermitted("product:create"));
    //查询用户的授权角色信息
    System.out.println("是否拥有admin的角色权限" + subject.hasRole("admin"));
    System.out.println("是否拥有superadmin的角色权限" + subject.hasRole("superadmin"));
    //退出登陆
    subject.logout();
    //退出登陆之后再查看权限
    System.out.println(subject.isAuthenticated());
    System.out.println("是否有删除用户的权限" + subject.isPermitted("user:delete"));
    System.out.println("是否有添加产品的权限" + subject.isPermitted("product:create"));
    
}
3.2.3.常见异常

UnknownAccountException:账号不存在

IncorrectCredentialsException:输入密码错误

DisabledAccountException:账号被禁用

LockedAccountException:登陆失败次数过多

ExpiredCredentialsException:凭证过期

3.2.4.身份认证流程

【Java】一文带你快速入门Shiro权限框架

  1. 首先调用 Subject.login(token) 进行登录,其会自动委托给SecurityManager
  2. SecurityManager 负责真正的身份验证逻辑;它会委托给Authenticator 进行身份验证
  3. Authenticator 才是真正的身份验证者,Shiro API 中核心的身份认证入口点,此处可以自定义插入自己的实现
  4. Authenticator 可能会委托给相应的 AuthenticationStrategy 进 行多 Realm 身份验证,默认 ModularRealmAuthenticator 会调用AuthenticationStrategy 进行多 Realm 身份验证
  5. Authenticator 会把相应的 token 传入 Realm,从 Realm 获取身份验证信息,如果没有返回/抛出异常表示身份验证失败了。此处可以配置多个Realm,将按照相应的顺序及策略进行访问

3.3.自定义Realm

​ 上边的程序使用的是Shiro自带的IniRealm,IniRealm从ini配置文件中读取用户的信息,大部分情况下需要从系统的数据库中读取用户信息,所以需要自定义realm,实现自定义Realm一般继承 AuthorizingRealm(授权)即可;其继承了AuthenticatingRealm(即身份验证),而且也间接继承了CachingRealm(带有缓存实现)

【Java】一文带你快速入门Shiro权限框架

3.3.1.相关代码

用户

public class User {
    //用户名、密码、用户状态
    private String username;
    private String password;
    //0锁定、1正常
    private String status;
}

自定义Realm认证部分代码

/**
 * 认证
 * @param token
 * @return
 * @throws AuthenticationException
 */
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
    //从令牌中获取到用户输入的用户名
    String usernmae = (String) token.getPrincipal();
    //获取用户输入的密码(因为获取的是二进制需要转换)
    String password = new String ((char[]) token.getCredentials());
    //模拟从数据库中获取对应的用户数据
    User admin = new User("admin", "123456","1");
    //进行信息比对
    if (!usernmae.equals(admin.getUsername())) {
        throw new UnknownAccountException("用户不存在");
    }
    if (!password.equals(admin.getPassword())){
        throw new IncorrectCredentialsException("密码错误");
    }
    if ("0".equals(admin.getStatus())){
        throw new LockedAccountException("账户被锁定,请联系管理员");
    }
    //如果没有异常则表示认证通过则返回一个简单的认证数据模型
    return new SimpleAuthenticationInfo(usernmae, password, getName());
}

自定义Realm授权部分代码

**
 * 授权
 * @param principalCollection
 * @return
 */
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
    //初始化一个简单授权对象
    SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo();
    //给授权对象设置权限
    //设置角色
    Set<String> roles = new HashSet<>();
    //模拟从数据库的角色表中获取角色添加信息
    roles.add("admin");
    roles.add("superadmin");
    //设置权限
    Set<String> permissions=new HashSet<>();
    permissions.add("user:create");
    permissions.add("user:delete");
    permissions.add("user:update");
    //添加到授权信息中
    authorizationInfo.setRoles(roles);
    authorizationInfo.setStringPermissions(permissions);

    return authorizationInfo;
}
3.3.2.配置与测试

关于Shiro.ini配置

在shiro.ini配置中需要将内容进行更新,不再使用手动进行认证,标明自定义Realm的类路径,使用自定义Realm。

#[users]
#zhangsan=123456,admin
#lisi=654321,superadmin
#
#[roles]
#admin=product:create,product:update,product:delete
#superadmin=product:create,product:update,product:delete

#自定义realm
shiroRealm=com.imcode.common.shiro.ShiroRelam
#将realm设置到securityManager
securityManager.realms=$shiroRealm

关于测试

@Test
public void demo02(){
    //通过shiro.ini初始化一个SecurityManager工厂
    IniSecurityManagerFactory iniSecurityManagerFactory=new IniSecurityManagerFactory("classpath:shiro.ini");
    //通过工厂获取一个SecurityManager管理器
    SecurityManager securityManager = iniSecurityManagerFactory.getInstance();
    //使用SecurityUtils将securityManager设置到运行环境中
    SecurityUtils.setSecurityManager(securityManager);
    //创建一个Subject实例
    Subject subject = SecurityUtils.getSubject();
    //创建token令牌,记录用户登陆的身份和凭证即账号密码
    UsernamePasswordToken user = new UsernamePasswordToken("admin", "123456");
    //登陆
    subject.login(user);
    //测试
    System.out.println(subject.isPermitted("user:create"));
    System.out.println(subject.hasRole("admin"));
}

3.4.关于Permissions

Shiro将Permission定义为定义显式行为或操作的语句。它是应用程序中原始功能的声明,仅此而已。权限是安全策略中最低级别的构造,它们只显式定义应用程序可以执行的操作。

3.4.1.简单案例

假设您希望添加对公司打印机的访问权限,以限制某些人可以打印到特定的打印机,而其他人可以查询当前队列。

一种非常简单的方法是授予用户“queryPrinter”权限。然后,您可以调用查看权限的方法来判断用户是否具有queryPrinter的权限:

subject.isPermitted("queryPrinter")
3.4.2.关于permissions规则

资源标识符:操作:对象实例 ID 即对哪个资源的哪个实例可以进行什么操作.

默认支持通配符权限字符串: 示资源/操作/实例的分割, 表示操作的分割* 表示任意资源/操作/实例

案例

例如:user:query、user:edit

– 冒号是一个特殊字符,它用来分隔权限字符串的下一部件:第一部分是权限被操作的领域,第二部分是被执行的操作

多个值

每个部分都可以包含多个值。因此,您不必向用户授予“printer:print”和“printer:query”权限,而只需授予他们一个权限:

printer:print,query

全部值

如果您想授予用户特定部分中的所有值,该怎么办?这样做比手动列出每个值更方便。同样,基于通配符,我们可以做到这一点。如果printer域有3个可能的行动(query,print,和manage),这一点

printer:query,print,manage

可以变成

printer:*

4.常用组件

4.1.关于加密

4.1.1.散列算法

散列算法一般用于生成一段文本的摘要信息,散列算法不可逆,将内容可以生成摘要,无法将摘要转成原始内容。散列算法常用于对密码进行散列,常用的散列算法有MD5、SHA。

​ 一般散列算法需要提供一个salt(盐)与原始内容生成摘要信息,这样做的目的是为了安全性,比如:111111的md5值是:96e79218965eb72c92a549dd5a330112,拿着“96e79218965eb72c92a549dd5a330112”去md5破解网站很容易进行破解,如果要是对111111和salt(盐,一个随机数)进行散列,这样虽然密码都是111111,但是加不同的盐会生成不同的散列值。

案例代码

@Test
public void test() {
    //md5加密,不加盐
    String password_md5 = new Md5Hash("111111").toString();
    System.out.println("password_md5=" + password_md5);

    //md5加密,加盐
    String password_md5_salt_1 = new Md5Hash("111111", "imcode", 1).toString();
    System.out.println("password_md5_salt_1=" + password_md5_salt_1);

    //两次散列相当于md5(md5())
    String password_md5_salt_2 = new Md5Hash("111111", "imcode", 2).toString();
    System.out.println("password_md5_salt_2=" + password_md5_salt_2);

}
4.1.2.加密工具类

可以将shiro自带的加密类写成一个通用类。

public class MD5Util {
    // 散列次数
    private static int hashIterations = 3;
    /**
     * md5加密工具类
     */
    public static String md5(String source, String salt) {
        return new Md5Hash(source, salt, hashIterations).toString();
    }
}
4.1.3.对密码进行加密

一般在数据库中的密码我们通常不会以明文的方式进行显示,会通过加密的方式加强密码的安全度。

@Test
public void test02(){
    //对密码进行加密
    ShiroUtil.login("admin",MD5Util.md5("123456","ak47"));
    Subject subject = SecurityUtils.getSubject();
    System.out.println(subject.hasRole("admin"));
    System.out.println(subject.isPermitted("user:create"));
}

4.2.关于缓存

利用缓存可以提高效率,比如用户登录后,其用户信息、拥有的角色/权限不必每次去查,这样可以提高效率。

4.2.1.场景

每次查询用户的权限的时候都会调用一次shiro的授权方法,使用缓存可以实现只有在用户认证成功的时候调用一下授权方法,后续不再调用该方法。我们使用ehcache作缓存.

4.2.2.相关配置

pom.xml

引入shiro对ehcache的支持包和ehcache包

<dependency>
    <groupId>org.apache.shiro</groupId>
    <artifactId>shiro-ehcache</artifactId>
    <version>1.3.2</version>
</dependency>

<dependency>
    <groupId>net.sf.ehcache</groupId>
    <artifactId>ehcache</artifactId>
    <version>2.10.5</version>
</dependency>

shiro.ini文件

#缓存管理器配置
cacheManager=org.apache.shiro.cache.ehcache.EhCacheManager
securityManager.cacheManager=$cacheManager

测试

@Test
public void test03(){
    //对密码进行加密
    ShiroUtil.login("admin",MD5Util.md5("123456","ak47"));
    Subject subject = SecurityUtils.getSubject();

    System.out.println(subject.hasRole("admin"));
    System.out.println(subject.isPermitted("user:create"));
//退出登录
    subject.logout();

    ShiroUtil.login("admin",MD5Util.md5("123456","ak47"));
    Subject subject2 = SecurityUtils.getSubject();
    System.out.println(subject2.hasRole("admin"));
    System.out.println(subject2.isPermitted("user:create"));

}
//测试发现,用户登录以后授权信息会被缓存,用户退出以后缓存的授权信息清空

🏜写在最后

以上内容为Shiro框架的初步入门,以及一些Shiro权限的小Demo案例

代码的学习过程中,手动实践才是最为重要的,多动手远胜多看。

【Java】一文带你快速入门Shiro权限框架文章来源地址https://www.toymoban.com/news/detail-472522.html

到了这里,关于【Java】一文带你快速入门Shiro权限框架的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 一文带你快速了解Python史上最快Web框架

    【作者主页】: 吴秋霖 【作者介绍】:Python领域优质创作者、阿里云博客专家、华为云享专家。长期致力于Python与爬虫领域研究与开发工作! 【作者推荐】:对JS逆向感兴趣的朋友可以关注《爬虫JS逆向实战》,对分布式爬虫平台感兴趣的朋友可以关注《分布式爬虫平台搭建

    2024年02月05日
    浏览(49)
  • 【前沿技术】一文带你快速入门 K8s

    👉 博主介绍 : 博主从事应用安全和大数据领域,有8年研发经验,5年面试官经验,Java技术专家,WEB架构师,阿里云专家博主,华为云云享专家,51CTO TOP红人 Java知识图谱点击链接: 体系化学习Java(Java面试专题) 💕💕 感兴趣的同学可以收藏关注下 , 不然下次找不到哟

    2024年02月16日
    浏览(42)
  • 一文带你入门Arco Design,快速构建一个Arco项目Demo

    确保你的机器中有Node.js和Git环境,如果没有,参考如下文章: Node.js安装及环境配置 Git安装配置教程 开始开发之前,请确认本地环境中安装好了 node , git 和 arco cli 其中 arco cli 是安装项目模版的工具,请运行以下命令安装: 在某一个文件夹下运行Shell,运行如下命令新建项

    2024年02月13日
    浏览(43)
  • 【算法】一文带你快速入门动态规划算法以及动规中的空间优化

    君兮_的个人主页 即使走的再远,也勿忘启程时的初心 C/C++ 游戏开发 Hello,米娜桑们,这里是君兮_,如果给算法的难度和复杂度排一个排名,那么动态规划算法一定名列前茅。在最开始没有什么整体的方法的时候,我也曾经被动态规划折磨过很长时间,通过我一段时间的刷题

    2024年02月05日
    浏览(42)
  • shiro 安全(权限)框架

    1.1、概述 Apache Shiro 是一个功能强大且易于使用的 Java 安全(权限)框架。Shiro 可以完成:认证、授权、加密、会话管理、与 Web 集成、缓存 等。借助 Shiro 您可以快速轻松地保护任何应用程序——从最小的移动应用程序到最大的 Web 和企业应用程序。 官网:https://shiro.apache.org/

    2024年02月06日
    浏览(45)
  • 安全(权限)框架Shiro概述及原理

    Apache Shiro 是一个功能强大且易于使用的 Java 安全(权限)框架。 Shiro 可以完成:认证、授权、加密、会话管理、与 Web 集成、缓存 等。借助 Shiro 您可以快速轻松地保护任何应用程序——从最小的移动应用程序到最大的 Web 和企业应用程序。 官网:https://shiro.apache.org/ 自 200

    2024年02月12日
    浏览(49)
  • SSM+Shiro安全框架整合(完成安全认证--登录+权限授权)+ssm整合shiro前后端分离

    目录 1.搭建SSM框架  1.1.引入相关的依赖 1.2. spring配置文件 1.3. web.xml配置文件 1.4.配置Tomcat并启动 2.ssm整合shiro---认证功能  (1).引入依赖 (2).修改spring配置文件 (3).修改web.xml文件 (4).新建login.jsp(登录页面) (5).新建success.jsp(登录成功后跳转到此) (6).创建User实体类 (7).创建LoginVo

    2024年02月15日
    浏览(43)
  • SpringBoot+Shiro框架整合实现前后端分离的权限管理基础Demo

    记录一下使用SpringBoot集成Shiro框架实现前后端分离Web项目的过程,后端使用SpringBoot整合Shiro,前端使用vue+elementUI,达到前后端使用token来进行交互的应用,这种方式通常叫做无状态,后端只需要使用Shiro框架根据前端传来的token信息授权访问相应资源。 案例源码:SpringBoot+Sh

    2024年02月06日
    浏览(45)
  • 【Linux】一文带你掌握Linux权限!

    最近,我发现了一个超级强大的人工智能学习网站。它以通俗易懂的方式呈现复杂的概念,而且内容风趣幽默。我觉得它对大家可能会有所帮助,所以我在此分享。点击这里跳转到网站。 🎉博客主页:小智_x0___0x_ 🎉欢迎关注:👍点赞🙌收藏✍️留言 🎉系列专栏:Linux入门

    2024年02月05日
    浏览(47)
  • 【操作系统】一文快速入门,很适合JAVA后端看

    作者简介: 目录 1.概述 2.CPU管理 3.内存管理 4.IO管理 操作系统可以看作一个计算机的管理系统,对计算机的硬件资源提供了一套完整的管理解决方案。计算机的硬件组成有五大模块:运算器、控制器、存储器、输入设备、输出设备。操作系统实际上就是对这个五块资源各自提

    2024年02月10日
    浏览(38)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包