SpringBoot——整合Shiro,实现安全认证和权限管理功能

目录

Shiro

项目总结

新建一个SpringBoot项目

pom.xml

application.properties(配置文件)

User(实体类)

UserMapper(数据访问层接口)

UserMapper.xml(数据库映射文件)

UserService(服务层接口)

UserServiceImpl(接口实现类)

UserRealm(认证、授权逻辑代码类)

ShiroConfig(Shiro配置类)

ShiroApplication(启动类)

index.html(主页面)

login.html(登录页面)

add.html(添加页面)

delete.html(删除页面)

项目测试


Shiro

  • Apache Shiro是一个开源的轻量级的Java安全框架,它提供身份验证、授权、密码管理以及会话管理等功能。相对于Spring Security,Shiro框架更加直观、易用,同时也能提供健壮的安全性
  • 在实际工作时可能使用小而简单的Shiro就足够了,不存在Shiro和Security哪个更好
  • Shiro支持的功能:
    • Authentication:用户身份认证、登录,验证用户是否拥有相应的身份
    • Authorization:授权,验证某个已认证的用户是否拥有某个权限
    • Session Management:会话管理,用户登录后就是第一次会话,在没有退出之前,用户的所有信息都在会话中
    • Cryptography:加密,保证数据的安全性,如将密码加密存储到数据库中
    • Web Support:Web支持,使系统 可以非常容易地集成到Web环境中
    • Caching:缓存,比如用户登录后,其用户信息,以及拥有的角色、权限不必每次都去查,这样可以提高效率
    • Concurrency:Shiro支持多线程应用的并发验证,如在一个线程中开启另一个线程,能把权限自动地传播过去
    • Testing:提供测试支持
    • Run As:允许一个用户冒用另一个用户的身份(如果他们允许)进行访问
    • Remember Me:一次登录后,之后登录不用输入用户名和密码

项目总结

  • 该项目是SpringBoot整合Shiro实现了用户管理系统中的登录认证和授权

  • 需求分析: 首先,明确项目的安全需求,包括用户认证、权限管理、会话管理等方面的具体要求。了解需要保护的资源和不同用户角色的访问权限。

  • 项目初始化: 使用 Spring Initializr 或其他工具创建一个新的 Spring Boot 项目。配置基本的项目结构和依赖管理(Maven 或 Gradle)。

  • 引入依赖: 在项目的 pom.xml 文件中添加 Shiro 的依赖项

  • 配置 Shiro: 创建一个 Shiro 配置类,用于配置安全管理器、Realm 和拦截器链等。

  • 实现 Realm: 创建自定义的 Realm 类,用于处理用户认证和授权逻辑。

  • 编写登录和权限控制代码: 创建控制器来处理用户登录和注销请求。

  • 测试与调试: 运行项目并进行各种测试,确保用户认证和授权功能正常工作。

新建一个SpringBoot项目

新建数据库、表

CREATE DATABASE shiro;
USE shiro;
CREATE TABLE IF NOT EXISTS `t_user`(
	`id` INT PRIMARY KEY COMMENT '用户ID(主键)',
    `username` VARCHAR(255) UNIQUE NOT NULL COMMENT '用户名',
    `password` VARCHAR(20) NOT NULL COMMENT '登录密码',
    `permissions` VARCHAR(100) NOT NULL COMMENT '用户权限'
)COMMENT='用户信息表';
INSERT INTO t_user(id,username,password,permissions) VALUE (1,'zhangsan','123','user:delete');
INSERT INTO t_user(id,username,password,permissions) VALUE (2,'lisi','123','user:add');

项目结构:

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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>
	<parent>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-parent</artifactId>
		<version>2.3.12.RELEASE</version>
		<relativePath/> <!-- lookup parent from repository -->
	</parent>
	<groupId>com.study</groupId>
	<artifactId>shiro</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<name>shiro</name>
	<description>Demo project for Spring Boot</description>
	<properties>
		<java.version>8</java.version>
	</properties>
	<dependencies>
		<!--MyBatis逆向工程-->
		<dependency>
			<groupId>org.mybatis.generator</groupId>
			<artifactId>mybatis-generator-maven-plugin</artifactId>
			<version>1.3.2</version>
		</dependency>

		<!--@Data注解-->
		<dependency>
			<groupId>org.projectlombok</groupId>
			<artifactId>lombok</artifactId>
		</dependency>

		<!--数据库-->
		<dependency>
			<groupId>mysql</groupId>
			<artifactId>mysql-connector-java</artifactId>
		</dependency>

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

        <!--为了在Thymeleaf中使用shiro标签,所以引入 thymeleaf-extras-shiro依赖-->
		<dependency>
			<groupId>com.github.theborakompanioni</groupId>
			<artifactId>thymeleaf-extras-shiro</artifactId>
			<version>2.1.0</version>
		</dependency>

		<!--shiro安全认证框架-->
		<dependency>
			<groupId>org.apache.shiro</groupId>
			<artifactId>shiro-spring-boot-web-starter</artifactId>
			<version>1.9.0</version>
		</dependency>

		<!--使用.html模板-->
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-thymeleaf</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-web</artifactId>
		</dependency>

		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-test</artifactId>
			<scope>test</scope>
		</dependency>
	</dependencies>

	<build>
		<plugins>
			<plugin>
				<groupId>org.springframework.boot</groupId>
				<artifactId>spring-boot-maven-plugin</artifactId>
			</plugin>
		</plugins>
	</build>

</project>

application.properties(配置文件)

# 配置shiro的基本信息
# 表示开启Shiro配置,默认为true
shiro.enabled=true  
# 表示开启Shiro Web配置,默认为true
shiro.web.enabled=true
# 表示登录地址,否则默认为"/login.jsp"
shiro.loginUrl=/login
# 表示登录成功地址,默认为"/"
shiro.successUrl=/index
# 表示未获授权默认跳转地址
shiro.unauthorizedUrl=/unauthorized
# 表示是否允许通过
shiro.sessionManager.sessionIdUrlRewritingEnabled=true
# UTL参数实现会话跟踪,如果网站支持Cookie,可以关闭此选项
# 表示是否允许通过Cookie实现会话跟踪,默认为true
shiro.sessionManager.sessionIdCookieEnabled=true

# MySQL数据库的配置信息
spring.datasource.username=root
spring.datasource.password=admin
spring.datasource.url=jdbc:mysql://localhost:3306/shiro?serverTimezone=UTC&useUnicode=true&characterEncoding=utf-8
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver

# mybatis的配置信息
# .xml文件放置处,此处指resources文件夹下
mybatis.mapper-locations=classpath:mapper/*.xml
mybatis.type-aliases-package=com.study.shiro.entity

User(实体类)

package com.study.shiro.entity;

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

@Data
@NoArgsConstructor
@AllArgsConstructor
public class User {
    private int id;
    private String username;
    private String password;
    private String permissions;
}

UserMapper(数据访问层接口)

package com.study.shiro.mapper;

import com.study.shiro.entity.User;
import org.apache.ibatis.annotations.Mapper;
import org.springframework.stereotype.Repository;

@Mapper
@Repository
public interface UserMapper{
    public User findUserByName(String username);
}

UserMapper.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.study.shiro.mapper.UserMapper">

    <resultMap id="BaseResultMap" type="com.study.shiro.entity.User">
            <id property="id" column="id" jdbcType="INTEGER"/>
            <result property="username" column="username" jdbcType="VARCHAR"/>
            <result property="password" column="password" jdbcType="VARCHAR"/>
            <result property="permissions" column="permissions" jdbcType="VARCHAR"/>
    </resultMap>

    <sql id="Base_Column_List">
        id,username,password,
        permissions
    </sql>
    <select id="findUserByName" resultType="com.study.shiro.entity.User">
        select * from t_user where username like #{username}
    </select>
</mapper>

UserService(服务层接口)

package com.study.shiro.service;

import com.study.shiro.entity.User;

public interface UserService{
    public User findUserByName(String username);
}

UserServiceImpl(接口实现类)

package com.study.shiro.service.impl;

import com.study.shiro.entity.User;
import com.study.shiro.mapper.UserMapper;
import com.study.shiro.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

@Service
public class UserServiceImpl implements UserService {

    @Autowired
    UserMapper userMapper;

    @Override
    public User findUserByName(String username) {
        return userMapper.findUserByName(username);
    }
}




UserRealm(认证、授权逻辑代码类)

package com.study.shiro.config;

import com.study.shiro.entity.User;
import com.study.shiro.service.UserService;
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.subject.PrincipalCollection;
import org.apache.shiro.subject.Subject;
import org.springframework.beans.factory.annotation.Autowired;

/**
 * 实现用户登录认证逻辑
 */
public class UserRealm extends AuthorizingRealm {

    @Autowired
    UserService userService;

    /**
     * 用户授权的逻辑代码
     */
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
        System.out.println("执行了===>用户授权");
        SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
        //获取当前登录的这个对象
        Subject subject = SecurityUtils.getSubject();
        //获取User对象
        User currentUser = (User) subject.getPrincipal();
        //设置权限
        info.addStringPermission(currentUser.getPermissions());

        return info;
    }

    /**
     * 用户认证的逻辑代码
     */
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
        System.out.println("执行了===>用户认证");
        UsernamePasswordToken token= (UsernamePasswordToken) authenticationToken;
        //连接真实的数据库,调取用户信息
        User user = userService.findUserByName(token.getUsername());
        //该用户不存在
        if(user==null){
            return null;
        }
        Subject subject = SecurityUtils.getSubject();
        //将登录用户放入Session中
        subject.getSession().setAttribute("loginUser",user);
        //密码认证
        return new SimpleAuthenticationInfo(user,user.getPassword(),"");
    }
}

ShiroConfig(Shiro配置类)

package com.study.shiro.config;

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

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

@Configuration
public class ShiroConfig {

    /**
     * ShiroDialect类是为了支持在Thymeleaf中使用的Shiro标签
     */
    @Bean
    public ShiroDialect getShiroDialect() {
        return new ShiroDialect();
    }

    @Bean
    public ShiroFilterFactoryBean shiroFilterFactoryBean(@Qualifier("securityManager") DefaultWebSecurityManager securityManager) {
        ShiroFilterFactoryBean bean = new ShiroFilterFactoryBean();

        // 设置安全管理器
        bean.setSecurityManager(securityManager);

        // Shiro内置过滤器,可以实现权限相关的拦截器
        /*
            常用的过滤器:
                anon: 无需认证(登录)可以访问
                authc: 必须认证才可以访问
                user: 如果使用rememberMe的功能可以直接访问
                perms: 该资源必须得到资源权限才可以访问
                role: 该资源必须得到角色权限才可以访问
         */
        Map<String, String> filterMap = new LinkedHashMap<>();
        filterMap.put("/login", "anon");
        filterMap.put("/index", "anon");
        filterMap.put("/doLogin", "anon"); // 无需认证即可访问
        filterMap.put("/logout", "logout"); // Shiro自带的退出登录
        filterMap.put("/**", "authc"); // 拦截其他所有请求,需要认证
        filterMap.put("/user/add","perms[user:add]");
        filterMap.put("/user/delete","perms[user:delete]");

        // 设置默认登录的 URL,身份认证失败会访问该 URL
        bean.setLoginUrl("/login");
        // 设置登录成功后要跳转的链接
        bean.setSuccessUrl("/index");
        //未授权时跳转的页面
        bean.setUnauthorizedUrl("/noauth");
        bean.setFilterChainDefinitionMap(filterMap);

        return bean;
    }

    @Bean(name = "securityManager")
    public DefaultWebSecurityManager getDefaultWebSecurityManager(@Qualifier("userRealm") UserRealm userRealm) {
        DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
        // 关联Realm
        securityManager.setRealm(userRealm);
        return securityManager;
    }

    /**
     * 创建Realm对象
     */
    @Bean(name = "userRealm")
    public UserRealm userRealm() {
        return new UserRealm();
    }
}

UserController(控制器)

package com.study.shiro.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.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 UserController {

    //主页面
    @RequestMapping({"/index","/"})
    public String index(Model model){
        model.addAttribute("msg","hello shiro!");
        return "index";
    }

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

    //处理登录请求,是否成功
    @RequestMapping("/doLogin")
    public String doLogin(String username,String password,Model model){
        //封装用户数据
        UsernamePasswordToken token = new UsernamePasswordToken(username, password);
        //获取当前用户
        Subject currentUser = SecurityUtils.getSubject();
        //执行登录的方法,只要没有异常就代表登录成功
        try {
            currentUser.login(token);
            return "index";
        } catch (UnknownAccountException uae) {
            model.addAttribute("msg","用户名不存在!");
            return "login";
        }catch (IncorrectCredentialsException ice){
            model.addAttribute("msg","密码错误!");
            return "login";
        }

    }

    //注销
    @RequestMapping("/logout")
    public String logout(){
        Subject currentUser = SecurityUtils.getSubject();
        currentUser.logout();
        return "index";
    }

    @RequestMapping("/noauth")
    @ResponseBody
    public String noAuth(){
        return "未经授权不能访问此页面";
    }

    //获取指定授权后,可访问该页面
    @RequestMapping("/user/add")
    public String add(){
        return "/user/add";
    }

    //获取指定授权后,可访问该页面
    @RequestMapping("/user/delete")
    public String delete(){
        return "/user/delete";
    }
}

ShiroApplication(启动类)

package com.study.shiro;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class ShiroApplication {

	public static void main(String[] args) {
		SpringApplication.run(ShiroApplication.class, args);
	}

}

index.html(主页面)

<!DOCTYPE html>
<html lang="en" xmlns:shiro="http://www.thymeleaf.org/thymeleaf-extras-shiro"
      xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title>主页面</title>
    <!--引入Bootstrap国内CDN库-->
    <link href="https://cdn.bootcss.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet">
</head>
<body>
<div class="container">
    <div class="row">
        <div class="col-md-4 col-md-offset-3">
            <h1>主页面</h1>
        </div>
    </div>
    <div class="row">
        <div class="col-md-4 col-md-offset-3">
            <!--会话中没有用户,即用户未登录,显示"登录"超链接-->
            <p th:if="${session.loginUser == null}">
                <a th:href="@{/login}">登录</a>
            </p>
        </div>
    </div>
    <div class="row">
        <div class="col-md-4 col-md-offset-3">
            <!--会话中保存了用户,即用户已登录,显示"注销"超链接-->
            <p th:if="${session.loginUser != null}">
                <a th:href="@{/logout}">注销</a>
            </p>
        </div>
    </div>
    <div class="row">
        <div class="col-md-4 col-md-offset-3">
            <div shiro:haspermission="user:add">
                <a th:href="@{/user/add}">添加</a>
            </div>
        </div>
    </div>
    <div class="row">
        <div class="col-md-4 col-md-offset-3">
            <div shiro:haspermission="user:delete">
                <a th:href="@{/user/delete}">删除</a>
            </div>
        </div>
    </div>
</div>
</body>
</html>

login.html(登录页面)

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title>登录页面</title>
    <link href="https://cdn.bootcss.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet">
</head>
<body>
    <div class="container">
        <div class="row">
            <div class="col-md-4 col-md-offset-3">
                <h1>登录页面</h1>
            </div>
        </div>
        <div class="row">
            <div class="col-md-4 col-md-offset-3">
                <p style="color:red;" th:text="${msg}"></p>
            </div>
        </div>
        <form class="form-horizontal" th:action="@{/doLogin}" method="post">
            <div class="form-group">
                <label class="col-sm-2 control-label">用户名</label>
                <div class="col-sm-4">
                    <input type="text" class="form-control" name="username">
                </div>
            </div>
            <div class="form-group">
                <label class="col-sm-2 control-label">密码</label>
                <div class="col-sm-4">
                    <input type="password" class="form-control" name="password">
                </div>
            </div>
            <div class="form-group">
                <div class="col-sm-offset-2 col-sm-10">
                    <button type="submit" class="btn btn-default">登录</button>
                </div>
            </div>
        </form>
    </div>
</body>
</html>

add.html(添加页面)

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>添加页面</title>
    <!--引入Bootstrap国内CDN库-->
    <link href="https://cdn.bootcss.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet">
</head>
<body>
<div class="container">
    <div class="row">
        <div class="col-md-4 col-md-offset-5"><h1>添加</h1></div>
    </div>
</div>
</body>
</html>

delete.html(删除页面)

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>删除页面</title>
    <!--引入Bootstrap国内CDN库-->
    <link href="https://cdn.bootcss.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet">
</head>
<body>
<div class="container">
    <div class="row">
        <div class="col-md-4 col-md-offset-5"><h1>删除</h1></div>
    </div>
</div>
</body>
</html>

项目测试

1、访问主页面:localhost:8080/index,点击“登录”

2、输入用户信息,登录

3、用户zhangsan拥有“删除”的权限

4、点击“注销”,返回用户登录页面

5、用户lisi,拥有“添加”的权限

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

第1章 物联网模式简介---物联网概述

物联网模式简介 物联网&#xff08;IoT&#xff09;在最近几年获得了巨大的吸引力&#xff0c;该领域在未来几年将呈指数级增长。这一增长将跨越所有主要领域/垂直行业&#xff0c;包括消费者、家庭、制造业、健康、旅游和运输。这本书将为那些想了解基本物联网模式以及如何混…

【2024大语言模型必知】做RAG时为什么要使用滑动窗口?句子窗口检索(Sentence Window Retrieval)是什么?

目录 1. 传统的向量检索方法&#xff0c;使用整个文档检索&#xff0c;为什么不行&#xff1f; 2.句子滑动窗口检索&#xff08;Sentence Window Retrieval&#xff09;工作原理 3.句子滑动窗口检索&#xff08;Sentence Window Retrieval&#xff09;的优点 1. 传统的向量检…

我在高职教STM32——时钟系统与延时控制(1)

大家好&#xff0c;我是老耿&#xff0c;高职青椒一枚&#xff0c;一直从事单片机、嵌入式、物联网等课程的教学。对于高职的学生层次&#xff0c;同行应该都懂的&#xff0c;老师在课堂上教学几乎是没什么成就感的。正因如此&#xff0c;才有了借助 CSDN 平台寻求认同感和成就…

十步学习法,赋能程序员

大家好&#xff0c;我是码农先森。 引言 最近看了《软技能&#xff1a;代码之外的生存指南》这本书&#xff0c;对其中的 “十步学习法”。 有一些感触&#xff0c;所以将其中的内容记录并总结了下来&#xff0c;分享给大家。 程序员在学习成长的过程中&#xff0c;除了关注…

Andorid Studio SSL peer shut down incorrectly

当我们打开Android Studio创建项目的时候&#xff0c;发现Gradle构建项目&#xff0c;下载依赖的速度非常之慢&#xff0c;那么聪明的我们会设置Android Studio的Proxy代理&#xff0c;如下&#xff01; 然后幸运的你可能下载速度会变快&#xff0c;但是也可能会有其他异常&…

3.x86游戏实战-寄存器

免责声明&#xff1a;内容仅供学习参考&#xff0c;请合法利用知识&#xff0c;禁止进行违法犯罪活动&#xff01; 本次游戏没法给 内容参考于&#xff1a;微尘网络安全 上一个内容&#xff1a;2.x86游戏实战-跨进程读取血量 寄存器说明&#xff1a; 寄存器是处理器的一部&…

【安全开发】内网扫描器

文章目录 前言现实现的功能较少后序开发会逐步加入简单漏洞探探测和代理功能。 一、开发过程1.项目结构2.main.go3.core模块3.1 scanner.go3.2 service.go 4.bruteforc4.1 bruteforce.go 二、使用步骤 前言 为什么要写这个&#xff1f; fscna被杀的概率太高&#xff08;哪天二…

从单一到多元:EasyCVR流媒体视频汇聚技术推动安防监控智能升级

随着科技的飞速发展&#xff0c;视频已成为我们日常生活和工作中的重要组成部分。尤其在远程办公、在线教育、虚拟会议等领域&#xff0c;视频的应用愈发广泛。为了满足日益增长的视频需求&#xff0c;流媒体视频汇聚融合技术应运而生&#xff0c;它不仅改变了传统视频的观看和…

江山欧派杯2024全国华佗五禽戏线上线下观摩交流比赛在亳州开幕

6月28日&#xff0c;2024全国华佗五禽戏线上线下观摩交流比赛在安徽省亳州市开幕。 此次比赛是由安徽省亳州市文化旅游体育局和安徽省非物质文化遗产保护中心主办、亳州市华佗五禽戏协会&#xff08;国家级非遗华佗五禽戏保护单位&#xff09;和亳州市传统华佗五禽戏俱乐部&…

【数字基础设施1007】探索数字基础设施的影响:宽带政策变量数据集来了!

今天给大家分享的是国内顶级期刊2023年发表论文《数字基础设施与代际收入向上流动性——基于“宽带中国”战略的准自然实验》使用到的重要数据集——“宽带中国”政策变量数据、互联网发展指数以及工具变量&#xff08;所在城市到杭州市的球面距离和到“八纵八横”政策节点城市…

2.最简单的hello驱动

写驱动最快的方法就是抄内核中的其他驱动&#xff0c;这里选择的是/Linux-4.9.88/drivers/char/mem.c 第一步新建一个hello_drv.c,把mem.c中的头文件都复制过来 #include <linux/mm.h> #include <linux/miscdevice.h> #include <linux/slab.h> #include <…

干货︱部分领域数字孪生白皮书及报告汇总(附下载)

在国家政策和市场需求的双轮驱动下&#xff0c;数字孪生技术越来越为人们所熟知。作为数字化的重要底层技术&#xff0c;数字孪生在优化各行各业产业布局、实现产业结构优化、打通生产上下游链条、迈向产业智能发展、推动行业高质量发展中发挥着重要作用。为了帮助广大读者朋友…

uni-app通过配置package.json实现环境变量、自定义条件编译

文章目录 前言官方提示使用方法微信小程序配置如下自定义条件编译使用方法 前言 uni-app 官方概括 官方文档 在开发web时&#xff0c;有时需要一套代码编译发布到不同的站点&#xff0c;比如主站和微信h5站。&#xff08;注意不是一套代码内部自适应不同浏览器&#xff0c;是真…

贾英才主任的中医探索之路

在北京崇文门中医医院&#xff0c;贾英才主任在中医领域的钻研从未停歇。他对药理的探究和药物搭配的研究&#xff0c;展现出了非凡的专注与执着。 贾英才主任常常埋首于浩瀚的中医典籍之中&#xff0c;逐字逐句地研读古代名医的论述&#xff0c;试图从那些古老的智慧中汲取精…

第十九课,编写并调用自定义函数

一&#xff0c;函数五大组成部分 因为其重要性故再此强调&#xff0c;参数列表可以为任意个数&#xff0c;返回值只能有一个&#xff08;请初学者暂时这样认为&#xff09; 特殊的&#xff0c;如果不需要返回结果&#xff0c;用None替代&#xff01; 二&#xff0c;编写自定义…

BUUCTF--WEB

首頁 - OWASP Top 10:2021 [极客大挑战 2019]EasySQL 类型:sql注入 使用万能密码 flag{f580db5b-c0c9-4b13-bfb6-adfa525c93f5} [极客大挑战 2019]Havefun 类型:代码审计 F12打开浏览器控制台 GET请求,在url添加参数/?cat=dog访问 返回flag{f60c7d5c-9f44-4e92-88c0…

操作系统期末复习(对抽象概念的简单形象化)

操作系统 引论 定义与基本概念&#xff1a;操作系统是计算机硬件与用户之间的桥梁&#xff0c;类似于家中的管家&#xff0c;它管理硬件资源&#xff08;如CPU、内存、硬盘&#xff09;&#xff0c;并为用户提供方便的服务&#xff08;应用程序执行、文件管理等&#xff09;。…

三星DRAM、NAND,“又双叒叕”带头涨价了

据韩国媒体《每日经济新闻》报道&#xff0c;三星电子计划在第三季度上调服务器DRAM和企业级NAND闪存的价格&#xff0c;涨幅预计在15%-20%&#xff0c;主要受人工智能(AI)需求激增的推动。这一举措有望提振公司下半年业绩。 据《经济日报》报道援引业内消息&#xff0c;由于厂…

数据资产赋能企业决策:通过精准的数据分析和洞察,构建高效的数据资产解决方案,为企业提供决策支持,助力企业实现精准营销、风险管理、产品创新等目标,提升企业竞争力

一、引言 在信息化和数字化飞速发展的今天&#xff0c;数据已成为企业最宝贵的资产之一。数据资产不仅包含了企业的基本信息&#xff0c;还蕴含了丰富的市场趋势、消费者行为和潜在商机。如何通过精准的数据分析和洞察&#xff0c;构建高效的数据资产解决方案&#xff0c;为企…

使用QGIS进行研究区域制图实战

目录 前言 一、QGIS的版本和数据介绍 1、关于QGIS版本 2、需要准备的数据 二、准备制图 1、制作全国区位图 2、矢量和遥感信息的编辑 三、出图编辑 1、设置主题信息 2、打印布局制作 3、美化地图 总结 前言 俗话说“一图胜千言”&#xff0c;在地理信息的领域中&…