Springboot集成shiro框架:

news2024/11/15 19:59:17

1, Shiro:是一个强大且易用的Java安全框架,执行身份验证、授权、密码和会话管理。

使用Shiro的易于理解的API,可以快速、轻松地获得任何应用程序,从最小的移动应用程序到最大的网络和企业应用程序。

2,三大组件:Subject、SecurityManager、Realm

Subject:
即“当前操作用户”。但是,在Shiro中,Subject这一概念并不仅仅指人,也可以是第三方进程、后台帐户(Daemon Account)或其他类似事物。它仅仅意味着“当前跟软件交互的东西”。

Subject代表了当前用户的安全操作,SecurityManager则管理所有用户的安全操作。

SecurityManager:
它是Shiro框架的核心,典型的Facade模式,Shiro通过SecurityManager来管理内部组件实例,并通过它来提供安全管理的各种服务。

Realm:
Realm充当了Shiro与应用安全数据间的“桥梁”或者“连接器”。也就是说,当对用户执行认证(登录)和授权(访问控制)验证时,Shiro会从应用配置的Realm中查找用户及其权限信息。

从这个意义上讲,Realm实质上是一个安全相关的DAO:它封装了数据源的连接细节,并在需要时将相关数据提供给Shiro。当配置Shiro时,你必须至少指定一个Realm,用于认证和(或)授权。配置多个Realm是可以的,但是至少需要一个。

Shiro内置了可以连接大量安全数据源(又名目录)的Realm,如LDAP、关系数据库(JDBC)、类似INI的文本配置资源以及属性文件等。如果缺省的Realm不能满足需求,你还可以插入代表自定义数据源的自己的Realm实现。
 

3,基本功能点:

Authentication:身份认证 / 登录,验证用户是不是拥有相应的身份;
Authorization:授权,即权限验证,验证某个已认证的用户是否拥有某个权限;即判断用户是否能做事情,常见的如:验证某个用户是否拥有某个角色。或者细粒度的验证某个用户对某个资源是否具有某个权限;
Session Management:会话管理,即用户登录后就是一次会话,在没有退出之前,它的所有信息都在会话中;会话可以是普通 JavaSE 环境的,也可以是如 Web 环境的;
Cryptography:加密,保护数据的安全性,如密码加密存储到数据库,而不是明文存储;
Web Support:Web 支持,可以非常容易的集成到 Web 环境;
Caching:缓存,比如用户登录后,其用户信息、拥有的角色 / 权限不必每次去查,这样可以提高效率;
Concurrency:shiro 支持多线程应用的并发验证,即如在一个线程中开启另一个线程,能把权限自动传播过去;
Testing:提供测试支持;
Run As:允许一个用户假装为另一个用户(如果他们允许)的身份进行访问;
Remember Me:记住我,这个是非常常见的功能,即一次登录后,下次再来的话不用登录了。

4,springboot集成shiro框架和mybatis框架,以及Thymeleaf模板:

        1,创建一个springboot项目。

        2,导入相关依赖:

<!-- Shiro 依赖 -->
        <dependency>
            <groupId>org.apache.shiro</groupId>
            <artifactId>shiro-spring</artifactId>
            <version>1.8.0</version>
        </dependency>

<!-- 使用Thymeleaf整合Shiro标签 -->
<dependency>
    <groupId>com.github.theborakompanioni</groupId>
    <artifactId>thymeleaf-extras-shiro</artifactId>
    <version>2.0.0</version>
</dependency>
<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
</dependency>
<dependency>
    <groupId>log4j</groupId>
    <artifactId>log4j</artifactId>
    <version>1.2.17</version>
</dependency>

<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>druid</artifactId>
    <version>1.1.12</version>
</dependency>

<dependency>
    <groupId>org.mybatis.spring.boot</groupId>
    <artifactId>mybatis-spring-boot-starter</artifactId>
    <version>2.1.0</version>
</dependency>

<dependency>
    <groupId>org.projectlombok</groupId>
    <artifactId>lombok</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-thymeleaf</artifactId>
    <version>2.6.1</version>
</dependency>

        3,创建各个类

bean

package com.bean;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

@Data
@AllArgsConstructor
@NoArgsConstructor
public class Student {

    private int id;
    private String name;
    private String password;
    private String perms;
}

service

接口:

package com.secvice;

import com.bean.Student;

public interface IStudentService {

    public Student queryStudentByName(String name);
}

实现类:

package com.secvice;

import com.bean.Student;
import com.mapper.StudentMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

@Service
public class StudentServiceImpl implements IStudentService {

    @Autowired
    StudentMapper studentMapper;

    @Override
    public Student queryStudentByName(String name) {
        return studentMapper.queryStudentByName(name);
    }
}

controller

package com.controller;

import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.IncorrectCredentialsException;
import org.apache.shiro.authc.UnknownAccountException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.session.Session;
import org.apache.shiro.subject.Subject;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

@Controller
public class MyController {

    @RequestMapping({"/index","/"})
    public String index(Model model){
        model.addAttribute("msg","hello shiro!!!");
        return "index";
    }
    @RequestMapping("/user/add")
    public String add(){
        return "user/add";
    }
    @RequestMapping("/user/update")
    public String update(){
        return "user/update";
    }
    @RequestMapping("/toLogin")
    public String toLogin(){
        return "login";
    }

    @RequestMapping("/login")
    public String login(String username,String password,Model model){
        //获取当前的用户
        Subject subject = SecurityUtils.getSubject();
        //用于封装用户的登录数据
        UsernamePasswordToken usernamePasswordToken
                = new UsernamePasswordToken(username,password);
        try{
            subject.login(usernamePasswordToken);//执行登录方法,如果没有异常说明OK
            return "index";
        }catch (UnknownAccountException u){//用户名不存在
            model.addAttribute("msges","用户名错误!!!");
            return "login";
        }catch (IncorrectCredentialsException i){
            model.addAttribute("msges","密码错误!!!");
            return "login";
        }
    }
    @RequestMapping("/unauthorized")
    @ResponseBody
    public String unauthorized(){
        return "未经授权不可登录!!!";
    }
}

mapper

mapper接口类:

package com.mapper;

import com.bean.Student;
import org.apache.ibatis.annotations.Mapper;
import org.springframework.stereotype.Repository;

@Repository
@Mapper
public interface StudentMapper {

    public Student queryStudentByName(String name);

}
mapper.xml:
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">


<mapper namespace="com.mapper.StudentMapper">
    <select id="queryStudentByName"  parameterType="String" resultType="Student">
        select * from student where name=#{name}
    </select>

</mapper>

HTML页面:

        index.html

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org"
      xmlns:shiro="http://www.thymeleaf.org/thymeleaf-extras-shiro">
<head>
    <meta charset="UTF-8">
    <title>首页</title>
</head>
<body>
<!--/*@thymesVar id="msg" type=""*/-->
<h1 th:text="${msg}">首页</h1>
<div th:if="${session.loginStudent==null}">
    <a th:href="@{/toLogin}">登录</a>
</div>
<div shiro:hasPermission="user:add">
    <a th:href="@{/user/add}">增加</a><br>
</div>
<div shiro:hasPermission="user:update">
    <a th:href="@{/user/update}">修改</a>
</div>

</body>
</html>

        login.html

<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head> 
    <meta charset="utf-8"> 
    <title>登录</title> 
</head>
<style>
    .a{
        text-align: center;
        margin-top:10%;

    }
    div{
        background-color: gray;
        height:255px;
        width: 30%;
        margin-left: 35%;
    }
    body{
        background-color: white;
    }
    input{
        width: 60%;
        height: 40px;
    }


</style>
<body>
<div class="a">
    <form method="post" th:action="@{/login}">
        <label>用户名</label><br>
        <input type="text" name="username"><br>
        <label>密码</label><br>
        <input type="password" name="password"><br>
        <p th:text="${msges}" style="color: red"></p>
        <input style="margin-top: 30px" type="submit">

    </form>
</div>

</body>
</html>

        add.html和update.html

 add.html:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>增加</title>
</head>
<body>
<h1>增加</h1>
</body>
</html>
update.html:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>修改</title>
</head>
<body>
<h1>修改</h1>

</body>
</html>

application.properties

mybatis.type-aliases-package=com.bean
mybatis.mapper-locations=classpath:mapper/*.xml

application.yml

spring:
  datasource:
    username: root
    password: root
    #?serverTimezone=UTC解决时区的报错
    url: jdbc:mysql://localhost:3306/test?serverTimezone=UTC&useUnicode=true&characterEncoding=utf-8
    driver-class-name: com.mysql.cj.jdbc.Driver
    type: com.alibaba.druid.pool.DruidDataSource


    #Spring Boot 默认是不注入这些属性值的,需要自己绑定
    #druid 数据源专有配置
    initialSize: 5
    minIdle: 5
    maxActive: 20
    maxWait: 60000
    timeBetweenEvictionRunsMillis: 60000
    minEvictableIdleTimeMillis: 300000
    validationQuery: SELECT 1 FROM DUAL
    testWhileIdle: true
    testOnBorrow: false
    testOnReturn: false
    poolPreparedStatements: true


    #配置监控统计拦截的filters,stat:监控统计、log4j:日志记录、wall:防御sql注入
    #如果允许时报错  java.lang.ClassNotFoundException: org.apache.log4j.Priority
    #则导入 log4j 依赖即可,Maven 地址:https://mvnrepository.com/artifact/log4j/log4j
    filters: stat,wall,log4j
    maxPoolPreparedStatementPerConnectionSize: 20
    useGlobalDataSourceStat: true
    connectionProperties: druid.stat.mergeSql=true;druid.stat.slowSqlMillis=500

ShiroConfig配置类:

package com.config;

import at.pollux.thymeleaf.shiro.dialect.ShiroDialect;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.util.LinkedHashMap;
import java.util.Map;

@Configuration
public class ShiroConfig {

    //ShiroFilterFactoryBean
    @Bean
    public ShiroFilterFactoryBean shiroFilterFactoryBean(@Qualifier("defaultWebSecurityManager") DefaultWebSecurityManager defaultWebSecurityManager){
        ShiroFilterFactoryBean shiroFilterFactoryBean=new ShiroFilterFactoryBean();
        //设置安全管理器
        shiroFilterFactoryBean.setSecurityManager(defaultWebSecurityManager);

        //添加shiro的内置过滤器
        /*anon:无需认证就可以访问
       * authc:必须认证了才能访问
       * user:必须有记住我功能才能使用
       * perms:拥有对某个资源的权限才能访问
       * role:拥有某个角色权限才能访问
        *
        * */

        Map<String, String> filterChainDefinitionMap=new LinkedHashMap<>();
//        filterChainDefinitionMap.put("/user/add","authc");
//        filterChainDefinitionMap.put("/user/update","authc");
        //授权,正常情况下,没有授权会跳到授权页面
        filterChainDefinitionMap.put("/user/add","perms[user:add]");
        filterChainDefinitionMap.put("/user/update","perms[user:update]");

        filterChainDefinitionMap.put("/user/*","authc");

        shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);

        //跳转到登录页面
        shiroFilterFactoryBean.setLoginUrl("/toLogin");

        //跳转到未授权页面
        shiroFilterFactoryBean.setUnauthorizedUrl("/unauthorized");
        return shiroFilterFactoryBean;
    }

    //DafaultWebSecurityManager
    @Bean//@Qualifier("userRealm")和userRealm关联
    public DefaultWebSecurityManager defaultWebSecurityManager(@Qualifier("userRealm") UserRealm userRealm){
        DefaultWebSecurityManager defaultWebSecurityManager=new DefaultWebSecurityManager();
        //关联userRealm
        defaultWebSecurityManager.setRealm(userRealm);
        return defaultWebSecurityManager;
    }

    //创建realm 对象 ,需要自定义类
    @Bean
    public UserRealm userRealm(){
        return new UserRealm();
    }

    //整合shiro和thymeleaf模版
    @Bean
    public ShiroDialect shiroDialect(){
        return new ShiroDialect();
    }

}
UserRealm类:
package com.config;

import com.bean.Student;
import com.secvice.IStudentService;
import org.apache.catalina.security.SecurityUtil;
import org.apache.shiro.SecurityUtils;
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.session.Session;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.subject.Subject;
import org.springframework.beans.factory.annotation.Autowired;

public class UserRealm extends AuthorizingRealm {

    @Autowired
    IStudentService studentService;

    //授权
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
        System.out.println("执行了==>授权doGetAuthorizationInfo");
        SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
            //授权add页面
            info.addStringPermission("user:add");
            //拿到当前登录的对象
           Subject subject = SecurityUtils.getSubject();
           //拿到student对象
        Student currentStudent = (Student) subject.getPrincipal();
        //添加权限访问
        info.addStringPermission(currentStudent.getPerms());


        return info;
    }

    //认证
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
        System.out.println("执行了==>认证doGetAuthenticationInfo");

        //获取登录用户的令牌,名字
        UsernamePasswordToken authenticationToken1 = (UsernamePasswordToken) authenticationToken;
        //连接数据库真实数据:用户名 密码
        Student student = studentService.queryStudentByName(authenticationToken1.getUsername());
        //判断数据库查询出来的不为空,为空则返回报错
        if(student==null){
            return null;
        }
        Subject currentSubject = SecurityUtils.getSubject();
        Session session = currentSubject.getSession();
        session.setAttribute("loginStudent",student);

        //密码认证,shiro自己判断
        return new SimpleAuthenticationInfo(student,student.getPassword(),"");
    }
}




数据库表,如图:

 

创建包文件大概如下:

 以上大概是shiro的学习总结!!!

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

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

相关文章

POSIX线程(二)

目录 一、前言 二、Thread Attributes 1、Setting the Detached State Attribute&#xff08;thread5.c&#xff09; 2、Thread Attributes Scheduling &#xff08;1&#xff09;Scheduling&#xff08;thread6.c&#xff09; 三、Canceling a Thread 1、Canceling a …

[附源码]计算机毕业设计医院门诊管理信息系统Springboot程序

项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; SSM mybatis Maven Vue 等等组成&#xff0c;B/S模式 M…

一篇打通线程 等待 中断

✨✨hello&#xff0c;愿意点进来的小伙伴们&#xff0c;你们好呐&#xff01; &#x1f43b;&#x1f43b;系列专栏&#xff1a;【JavaEE初阶】 &#x1f432;&#x1f432;本篇内容&#xff1a;介绍 线程的 中断,等待的区别 &#x1f42f;&#x1f42f;作者简介:一名现大二的…

思科防火墙——实验练习加命令

作者简介&#xff1a;一名在校云计算网络运维学生、每天分享网络运维的学习经验、和学习笔记。 座右铭&#xff1a;低头赶路&#xff0c;敬事如仪 个人主页&#xff1a;网络豆的主页​​​​​​ 目录 前言 一.实验练习 1.实验&#xff08;1&#xff09;配置ASA接口 2.实…

HTML网页制作代码——简约的旅游图文相册博客HTML模板(12页)HTML+CSS+JavaScript 静态HTML旅行主题网页作业

&#x1f468;‍&#x1f393;学生HTML静态网页基础水平制作&#x1f469;‍&#x1f393;&#xff0c;页面排版干净简洁。使用HTMLCSS页面布局设计,web大学生网页设计作业源码&#xff0c;这是一个不错的旅游网页制作&#xff0c;画面精明&#xff0c;排版整洁&#xff0c;内容…

大学生个人网页设计 HTML个人网页制作 web个人网站模板 简单静态HTML个人网页作品

&#x1f389;精彩专栏推荐&#x1f447;&#x1f3fb;&#x1f447;&#x1f3fb;&#x1f447;&#x1f3fb; ✍️ 作者简介: 一个热爱把逻辑思维转变为代码的技术博主 &#x1f482; 作者主页: 【主页——&#x1f680;获取更多优质源码】 &#x1f393; web前端期末大作业…

[JavaEE]初始操作系统--进程

专栏简介: JavaEE从入门到进阶 题目来源: leetcode,牛客,剑指offer. 创作目标: 记录学习JavaEE学习历程 希望在提升自己的同时,帮助他人,,与大家一起共同进步,互相成长. 学历代表过去,能力代表现在,学习能力代表未来! 目录 1. javaEE概述 2. 计算机发展史 3. 冯诺依曼体系 …

Allegro如何移动器件操作指导

Allegro如何移动器件操作指导 Allegro上可以任意移动器件,具体操作如下 选择Edit-move Find选择Symbols Point根据需要选择 Sym Origin是抓取器件的原点 Body center是抓取器件的中心 User Pick可以自定义抓取的原点,在移动整个模块的并且旋转的时候常用的命令 Sym Pin#设…

投稿时要求注册ORCID,这张学术界身份证到底有哪些用处?

您是否经常遇到向国际期刊投稿时需要提供ORCID账号进行登录呢&#xff1f; 又是否在我们看到喜欢的文献时&#xff0c;不免被其作者圈粉&#xff0c;忍不住要去了解这位学者的其他作品和动向时却又很难搜到准确信息&#xff1f; 对中国学者来说&#xff0c;由于投到国际期刊时…

【Matplotlib绘制图像大全】(七):Matplotlib使用xlim()和ylim()修改轴线刻度

前言 大家好,我是阿光。 本专栏整理了《Matplotlib绘制图像大全》,内包含了各种常见的绘图方法,以及Matplotlib各种内置函数的使用方法,帮助我们快速便捷的绘制出数据图像。 正在更新中~ ✨ 🚨 我的项目环境: 平台:Windows10语言环境:python3.7编译器:PyCharmMatp…

Docker-compose部署XWiki

XWiki是一个知识管理平台&#xff0c;用于知识库管理和知识管理。最有名的是Confluence系统&#xff0c;我们现在搭建的是XWiki&#xff0c;这是一个开源系统。 我们可以到官网上查找安装的方法&#xff1a; 这里&#xff0c;我们采用PostgresSQL on Tomcat的方法&#xff1a;…

15.位操作

文章目录位操作15.1二进制数、位和字节15.1.1二进制整数15.1.2有符号整数(?)15.1.3二进制浮点数1.二进制小数2.浮点数表示法15.2其他进制数15.2.1八进制15.2.2十六进制15.3C按位运算符1.二进制反码或按位取反&#xff1a;~2.按位与&#xff1a;&3.按位或&#xff1a;|4.按…

HTML+CSS网页设计期末课程大作业 【茶叶文化网站设计题材】web前端开发技术 web课程设计 网页规划与设计

&#x1f389;精彩专栏推荐 &#x1f4ad;文末获取联系 ✍️ 作者简介: 一个热爱把逻辑思维转变为代码的技术博主 &#x1f482; 作者主页: 【主页——&#x1f680;获取更多优质源码】 &#x1f393; web前端期末大作业&#xff1a; 【&#x1f4da;毕设项目精品实战案例 (10…

[附源码]计算机毕业设计springboot校园代取快递系统

项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; SSM mybatis Maven Vue 等等组成&#xff0c;B/S模式 M…

dreamweaver作业静态HTML网页设计——我的家乡海南旅游网站

家乡旅游景点网页作业制作 网页代码运用了DIV盒子的使用方法&#xff0c;如盒子的嵌套、浮动、margin、border、background等属性的使用&#xff0c;外部大盒子设定居中&#xff0c;内部左中右布局&#xff0c;下方横向浮动排列&#xff0c;大学学习的前端知识点和布局方式都有…

LIO-SAM源码解析(五):mapOptmization.cpp

1. 代码流程 1.1. extractSurroundingKeyFrames() 1.2. scan2MapOptimization() 这个函数主要就是进行帧到地图的匹配&#xff0c;通过点到面、点到线的距离距离最小作为优化目标。LOAM中雅阁比矩阵推导其实还是过于复杂了&#xff0c;可以使用进行误差扰动来计算雅阁比矩阵&a…

Unity事件函数的执行顺序

事件函数的执行顺序 脚本生命周期流程图 场景加载时 这些函数在场景开始时被调用&#xff08;场景中的每个对象一次&#xff09;Awake&#xff1a;此函数总是在任何 Start 函数之前以及在预制件被实例化之后调用&#xff08;如果 GameObject 在启动期间处于非活动状态&#xf…

好家伙!阿里并发核心编程宝典(2022版)一夜登顶Github热榜第三

不知道大家今年的金九银十是否有出去面试过&#xff1f;有出去面试的朋友肯定深有感受&#xff0c;像我们刚入行那会面试的加分项现在卷得已经成为了面试的基础题&#xff08;手动狗头&#xff09;。其中最典型的就属这个Java并发编程了。之前一般只有大厂才会有高并发编程相关…

[附源码]Python计算机毕业设计Django基于vuejs的爱宠用品销售app

项目运行 环境配置&#xff1a; Pychram社区版 python3.7.7 Mysql5.7 HBuilderXlist pipNavicat11Djangonodejs。 项目技术&#xff1a; django python Vue 等等组成&#xff0c;B/S模式 pychram管理等等。 环境需要 1.运行环境&#xff1a;最好是python3.7.7&#xff0c;…

three.js之模型

文章目录简介网格模型旋转平移缩放方法平移旋转属性缩放位置平移旋转复制与克隆复制方法克隆方法注意专栏目录请点击 简介 我们常见的模型有点模型&#xff0c;线模型、网格模型他们的分类如下 点模型 Points对应的材质为点材质PointsMaterial 线模型 Line 线渲染模式Line…