Apache Shiro 使用教程

news2025/3/19 4:48:22

Apache Shiro 使用教程

Apache Shiro是一个强大且灵活的开源安全框架,主要用于处理身份验证(Authentication)、授权(Authorization)、加密(Cryptography)和会话管理(Session Management)等安全相关的任务。它简化了在Java应用程序中集成安全功能的复杂性,广泛适用于各种类型的项目,如Web应用、命令行工具等。本教程将深入介绍Shiro的各个核心概念和功能,并通过一个基于Spring Boot的示例项目展示如何在项目中实际使用Shiro。

一、Shiro 核心概念

1.1 Subject

Subject是Shiro的核心概念,它代表一个实体,可以是用户、服务或其他任何需要与安全系统交互的主体。通过Subject,开发者可以执行认证、授权、会话管理等操作。例如,当用户登录系统时,实际上是通过Subject进行身份验证;当需要检查用户是否有权限执行某个操作时,也是通过Subject进行授权判断。

1.2 SecurityManager

SecurityManager是Shiro的安全管理中心,负责协调和管理所有的安全操作。它就像是一个大脑,接收来自Subject的请求(如登录、权限检查等),并委派相应的Realm去获取和处理安全数据。在一个应用程序中,通常只需要一个SecurityManager实例,它是整个Shiro安全体系的核心。

1.3 Realm

Realm是Shiro用于获取安全数据的组件,它定义了数据源的来源,比如数据库、LDAP(轻量级目录访问协议)、内存等。Realm负责从特定的数据源中读取用户信息、角色信息和权限信息等,以支持SecurityManager进行认证和授权操作。开发者需要根据实际需求实现自定义的Realm或者使用Shiro提供的默认Realm

二、Shiro 的核心功能

2.1 身份验证(Authentication)

身份验证是确认用户身份的过程,通常通过用户名和密码或其他凭证来完成。Shiro提供了简单的接口和方法,让开发者可以方便地实现身份验证逻辑。当用户提交登录请求时,Subject会调用login方法进行身份验证,SecurityManager会将验证请求委派给配置的RealmRealm根据用户提供的凭证在数据源中查找匹配的用户信息,如果找到且凭证验证通过,则身份验证成功;否则,抛出身份验证异常。

2.2 授权(Authorization)

授权是确定用户是否有权限访问特定资源或执行某个操作的过程。Shiro通过角色和权限的概念来实现授权管理。开发者可以为用户分配角色,为角色分配权限,然后在代码中通过SubjectisPermittedhasRole方法来检查用户是否具有相应的权限或角色。例如,在一个文件管理系统中,只有具有“管理员”角色的用户才有权删除文件,Shiro就可以通过授权机制来确保只有授权用户可以执行此操作。

2.3 加密(Cryptography)

Shiro提供了多种加密算法和工具,用于保护敏感信息,如用户密码的存储和加密传输等。例如,可以使用HashedCredentialsMatcher来对用户密码进行哈希加密存储,防止密码泄露后被直接获取。Shiro还支持对称加密和非对称加密算法,满足不同场景下的加密需求。

2.4 会话管理(Session Management)

Shiro提供了会话管理功能,用于跟踪和管理用户的会话状态。在一个Web应用中,用户的会话状态可以包含用户的登录状态、登录时间、最近访问的页面等信息。Shiro的会话管理机制允许开发者在不同的应用服务器和分布式环境中轻松地管理用户会话,并且提供了会话监听器、会话过期处理等功能,方便开发者进行定制和扩展。

三、基于Spring Boot集成Shiro的示例

3.1 创建Spring Boot项目

首先,创建一个基于Spring Boot的Web应用项目。可以使用Spring Initializr(https://start.spring.io/ )工具快速创建项目,选择以下依赖:
• Spring Web
• Spring Boot DevTools(可选,用于开发时的热部署和快速重启)

3.2 添加Shiro依赖

在项目的pom.xml文件中添加Shiro和Shiro与Spring集成的依赖:

<dependency>
    <groupId>org.apache.shiro</groupId>
    <artifactId>shiro-spring-boot-web-starter</artifactId>
    <version>1.9.1</version>
</dependency>

3.3 配置Shiro

创建一个配置类ShiroConfig,用于配置Shiro的核心组件,包括SecurityManagerRealm和过滤器链等:

import org.apache.shiro.realm.Realm;
import org.apache.shiro.spring.web.config.DefaultShiroFilterChainDefinition;
import org.apache.shiro.spring.web.config.ShiroFilterChainDefinition;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class ShiroConfig {

    @Bean
    public Realm realm() {
        // 这里可以创建自定义Realm或使用Shiro提供的默认Realm
        return new CustomRealm();
    }

    @Bean
    public DefaultWebSecurityManager securityManager() {
        DefaultWebSecurityManager manager = new DefaultWebSecurityManager();
        manager.setRealm(realm());
        return manager;
    }

    @Bean
    public ShiroFilterChainDefinition shiroFilterChainDefinition() {
        DefaultShiroFilterChainDefinition chainDefinition = new DefaultShiroFilterChainDefinition();
        // 配置路径的访问权限,anon表示无需认证,authc表示需要认证
        chainDefinition.addPathDefinition("/login", "anon");
        chainDefinition.addPathDefinition("/logout", "logout");
        chainDefinition.addPathDefinition("/**", "authc");
        return chainDefinition;
    }
}

3.4 自定义Realm

创建一个自定义的RealmCustomRealm,用于从数据库或其他数据源中获取用户信息和权限信息:

import org.apache.shiro.authc.*;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;

import java.util.HashSet;
import java.util.Set;

public class CustomRealm extends AuthorizingRealm {

    // 用户认证
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
        UsernamePasswordToken upToken = (UsernamePasswordToken) token;
        String username = upToken.getUsername();

        // 模拟从数据库中获取用户信息
        if (!"admin".equals(username) &&!"user".equals(username)) {
            throw new UnknownAccountException("用户不存在");
        }

        String password = "123456"; // 实际应用中应从数据库获取真实的用户密码
        return new SimpleAuthenticationInfo(username, password, getName());
    }

    // 用户授权
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
        String username = (String) principals.getPrimaryPrincipal();
        SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo();

        // 模拟从数据库中获取用户角色和权限
        if ("admin".equals(username)) {
            authorizationInfo.addRole("admin");
            authorizationInfo.addStringPermission("user:delete");
        } else if ("user".equals(username)) {
            authorizationInfo.addRole("user");
            authorizationInfo.addStringPermission("user:view");
        }

        return authorizationInfo;
    }
}

3.5 编写控制器

创建一个控制器类ShiroController,用于处理登录、访问受保护资源等请求:

import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.subject.Subject;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class ShiroController {

    @GetMapping("/login")
    public String loginPage() {
        return "登录页面";
    }

    @PostMapping("/login")
    public String login(@RequestParam String username, @RequestParam String password) {
        Subject subject = SecurityUtils.getSubject();
        UsernamePasswordToken token = new UsernamePasswordToken(username, password);
        try {
            subject.login(token);
            return "登录成功";
        } catch (AuthenticationException e) {
            return "登录失败: " + e.getMessage();
        }
    }

    @GetMapping("/logout")
    public String logout() {
        SecurityUtils.getSubject().logout();
        return "已登出";
    }

    @GetMapping("/protected")
    public String protectedResource() {
        Subject subject = SecurityUtils.getSubject();
        if (subject.isAuthenticated()) {
            return "访问受保护资源成功";
        } else {
            return "请先登录";
        }
    }
}

3.6 测试应用

启动Spring Boot应用程序,访问http://localhost:8080/login ,可以看到登录页面。通过表单或发送POST请求(http://localhost:8080/login?username=admin&password=123456 )进行登录。登录成功后,可以访问受保护的资源http://localhost:8080/protected ,如果未登录则会被拦截并重定向到登录页面。同时,可以访问http://localhost:8080/logout 来登出当前用户。

四、总结

本教程介绍了Apache Shiro的核心概念和主要功能,包括身份验证、授权、加密和会话管理。通过一个基于Spring Boot的示例项目,展示了如何配置和使用Shiro来实现简单的安全控制。在实际项目中,你可以根据需求进一步扩展和定制Shiro的功能,如集成数据库、实现更复杂的权限管理逻辑等。Shiro作为一个成熟且强大的安全框架,能够大大简化Java应用程序中的安全开发工作,提高应用程序的安全性和可靠性。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2317571.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

智慧社区3.0

项目介绍&#xff1a; 此项目旨在推动成都市探索**超大城市社区发展治理新路**&#xff0c;由三个实验室负责三大内容 1、**研发社区阵地空间管理模块**&#xff1a;AI算法实现态势感知&#xff08;如通过社区图片和视频、文本&#xff0c;对环境 空间质量、绿视率、安全感分…

Springboot+Vue登录、注册功能(含验证码)(后端!)

我们首先写一个接口&#xff0c;叫login&#xff01;然后对传入一个user&#xff0c;因为我们前端肯定是要传过来一个user&#xff0c;然后我们后端返回一个user&#xff0c;因为我们要根据这个去校验&#xff01;我们还引入了一个hutool的一个东西&#xff0c;在pom文件里面引…

搞定python之八----操作mysql

本文是《搞定python》系列文章的第八篇&#xff0c;讲述利用python操作mysql数据库。相对来说&#xff0c;本文的综合性比较强&#xff0c;包含了操作数据库、异常处理、元组等内容&#xff0c;需要结合前面的知识点。 1、安装mysql模块 PyMySql模块相当于数据库的驱动&#…

LVGL 中设置 UI 层局部透明,显示下方视频层

LVGL层次 LVGL自上而下分别是layer_sys > layer_top > lv_sreen_active > layer_bottom 即 系统层、顶层、活动屏幕、底层 原理 如果将UI设置为局部透明&#xff0c;显示下方的视频层&#xff0c;不仅仅需要将当前活动屏幕的背景设置为透明&#xff0c;还需要将底层…

21.多态

一、多态概念 多种形态。 静态多态&#xff1a;编译时多态。&#xff08;函数重载&#xff09; 动态多态&#xff1a;运行时多态。&#xff08;继承关系下&#xff0c;调用父类指针或引用&#xff0c;对于不同的对象有不同的行为&#xff09; 二、多态的定义及实现 1&#xff…

【蓝桥杯】第十三届C++B组省赛

⭐️个人主页&#xff1a;小羊 ⭐️所属专栏&#xff1a;蓝桥杯 很荣幸您能阅读我的文章&#xff0c;诚请评论指点&#xff0c;欢迎欢迎 ~ 目录 试题A&#xff1a;九进制转十进制试题B&#xff1a;顺子日期试题C&#xff1a;刷题统计试题D&#xff1a;修剪灌木试题E&#xf…

C# PaddleOCR字符识别

1 安装Nuget 2 C# using System; using OpenCvSharp; using Sdcb.PaddleOCR; using Sdcb.PaddleOCR.Models.Local; using Sdcb.PaddleOCR.Models; using Sdcb.PaddleInference;namespace ConsoleApp1 {public class MichaelOCR{string imagePath "D:\\BUFFER\\VS\\Text\…

多环境开发-Profiles

在实际的项目开发中&#xff0c;我们通常会涉及多个环境&#xff0c;如开发环境&#xff08;dev&#xff09;、测试环境&#xff08;test&#xff09;和生产环境&#xff08;pro&#xff09;。在不同的环境下&#xff0c;程序的配置信息会有所不同&#xff0c;例如连接的数据库…

《TCP/IP网络编程》学习笔记 | Chapter 18:多线程服务器端的实现

《TCP/IP网络编程》学习笔记 | Chapter 18&#xff1a;多线程服务器端的实现 《TCP/IP网络编程》学习笔记 | Chapter 18&#xff1a;多线程服务器端的实现线程的概念引入线程的背景线程与进程的区别 线程创建与运行pthread_createpthread_join可在临界区内调用的函数工作&#…

MambaVision:一种Mamba-Transformer混合视觉骨干网络

摘要 我们提出了一种新型混合Mamba-Transformer主干网络&#xff0c;称为MambaVision&#xff0c;该网络专为视觉应用而设计。我们的核心贡献包括重新设计Mamba公式&#xff0c;以增强其对视觉特征的高效建模能力。此外&#xff0c;我们还对将视觉Transformer&#xff08;ViT&…

深度学习-服务器训练SparseDrive过程记录

1、cuda安装 1.1 卸载安装失败的cuda 参考&#xff1a;https://blog.csdn.net/weixin_40826634/article/details/127493809 注意&#xff1a;因为/usr/local/cuda-xx.x/bin/下没有卸载脚本&#xff0c;很可能是apt安装的&#xff0c;所以通过执行下面的命令删除&#xff1a; a…

学习单片机需要多长时间才能进行简单的项目开发?

之前有老铁问我&#xff0c;学单片机到底要多久&#xff0c;才能进行简单的项目开发&#xff1f;是三个月速成&#xff0c;还是三年磨一剑&#xff1f; 今天咱们就来聊聊这个话题&#xff0c;我不是什么高高在上的专家&#xff0c;就是个踩过无数坑、烧过几块板子的“技术老友”…

stm32 L432KC(mbed)入门第一课

目录 一. 前言 二. 专栏意义 三. MS入门第一课 一. 前言 新的一年MS课程又开始了&#xff0c;同时也到了该专栏的第三个年头。在前两年中&#xff0c;该专栏帮助了很多第一次接触单片机的同学。其中&#xff0c;有的同学订阅专栏是为了更好的完成并且通过MS这门课程&#xf…

批量给 Excel 添加或删除密码保护|Excel 批量设置打开密码和只读密码

我们在将 Excel 文档发送给第三方或者进行存档的时候&#xff0c;对 Excel 文档添加密码保护是非常重要的一个操作。添加保护后的 Excel 文档。就只能有相应权限的用户才能够打开或者编辑操作。尤其是当我们 Excel 文档中内容非常敏感非常重要的时候&#xff0c;添加保护就显得…

4.JVM-垃圾回收介绍

记录个人学习中记录笔记&#xff0c;如有错误请您指正&#xff0c;谢谢&#x1f64f; 垃圾回收器发展史 传统垃圾回收: 分代回收 不同代有不同的垃圾回收机制 保底 标记清除算法 垃圾识别算法 引用计数法 缺陷:下图2 出现循环引用 无法解决 可达性分析 大部分(Java,pytho…

Redis-锁-商品秒杀防止超卖

一、秒杀&#xff08;Seckill&#xff09;​ 1. ​定义 ​秒杀&#xff1a;短时间内&#xff08;如1秒内&#xff09;大量用户同时抢购 ​限量低价商品 的营销活动。​典型场景&#xff1a;双11热门商品抢购、小米手机首发、演唱会门票开售。 2. ​技术挑战 挑战点说明后果…

第一个vue项目

项目目录 启动vue项目 npm run serve 1.vue.config.js文件 (CLI通过vue-cli-serve启动项目&#xff0c;解析配置配置文件vue-condig-js&#xff09; // vue.config.js //引入path板块&#xff0c;这是Node.js的一个内置模块&#xff0c;用于处理文件路径&#xff0c;这里引用…

基于CNN的多种类蝴蝶图像分类

基于CNN的多种类蝴蝶图像分类&#x1f98b; 基于卷积神经网络对64992786张图像&#xff0c;75种不同类别的蝴蝶进行可视化分析、模型训练及分类展示 导入库 import pandas as pd import os import matplotlib.pyplot as plt import seaborn as sns import numpy as np from …

Unity插件-适用于画面传输的FMETP STREAM使用方法(三)基础使用

目录 一、插件介绍 二、组件介绍 三、Game View Streaming 1、使用 FM Network UDP 的基本设置 Server Scene Client Scene 2、使用使用 FM WebSocket 的基本设置 四、Audio Streaming 五、Microphone Streaming 一、插件介绍 ​​​​​​Unity插件-适用于画面传输的…

微信小程序wx.request接口报错(errno: 600001, errMsg: “request:fail -2:net::ERR_FAILED“)

来看看报错 报错如下: 请求发送部分,代码如下: uni.request({url: self.serverUrl "/getRealName",method: GET,data: {"code": self.info.code,},header: {"Authorization": uni.getStorageSync(tokenHead) uni.getStorageSync(token)}}…