Spring Security学习

系列文章目录

第一章 基础知识、数据类型学习
第二章 万年历项目
第三章 代码逻辑训练习题
第四章 方法、数组学习
第五章 图书管理系统项目
第六章 面向对象编程:封装、继承、多态学习
第七章 封装继承多态习题
第八章 常用类、包装类、异常处理机制学习
第九章 集合学习
第十章 IO流、多线程学习
第十一章 仓库管理系统JavaSE项目
第十二章 员工管理系统、多表查询、反射实现DBHelper学习
第十三章 DML、DDL、数据库对象学习
第十四章 网络编程、各种标签、CSS学习
第十五章 ECMAScript、BOM学习
第十六章 DOM、jQuery学习
第十七章 servlet、jsp、Cookie、Ajax学习
第十八章 融资管理系统JavaWeb项目
第十九章 MyBatis框架学习
第二十章 逆向工程、Spring框架IOC、AOP学习
第二十一章 SpringMVC框架学习
第二十二章 SpringBoot框架学习
第二十三章 招聘网站框架项目
第二十四章 Vue介绍、窗体内操作、窗体间操作学习
第二十六章 Vue路由配置、网络请求访问框架项目、element组件介绍学习
第二十五章 标准管理系统Vue项目
第二十六章 Linux安装、Nginx反向代理、负载均衡学习
第二十七章 Docker学习
第二十八章 Jenkins学习
第二十九章 Nexus学习
第三十章 Spring Security学习


文章目录

  • 系列文章目录
  • 前言
  • 一、Spring Security介绍
    • 1. Spring Security介绍
    • 2. Spring Security特性
  • 二、Spring Security代码编写:第一阶段
    • 1. 创建Maven项目
    • 2. 在pom文件里添加依赖
    • 3. 目录结构
    • 4. SecurityController文件
    • 5. 配置SpringBootMain文件
    • 6. application.yml文件
    • 7. main.html文件
    • 8. 启动项目
  • 三、Spring Security代码编写:第二阶段
    • 1. 第二阶段第三阶段总体结构图
    • 2. 在pom文件里添加依赖
    • 3. SecurityConfig文件
    • 4. UserDetailsServiceImpl文件
    • 5. login.html文件
    • 6. 实现效果
  • 四、Spring Security代码编写:第三阶段
    • 1. RememberMeConfig文件
    • 2. SecurityConfig文件
    • 3. login.html更改
    • 4. 创建数据库和表
    • 5. 实现效果
  • 五、Spring Security代码编写:第四阶段
    • 1. 项目结构
    • 2. 在pom文件里添加依赖
    • 3. 新增show.html界面
    • 4. 更新UserDetailsServiceImpl文件返回值
    • 5. 实现效果
  • 六、CSRF
  • 总结


前言

本文我们要讲述:
Spring Security
在下攸攸太上,是有人类女友的外星来客。


一、Spring Security介绍

1. Spring Security介绍

Spring Security是一个功能强大且灵活的安全框架,用于在Spring应用程序中提供身份验证授权、保护和攻击防护等安全功能。它提供了大量的配置选项和扩展机制,使开发者能够轻松地集成和定制应用程序的安全需求。

2. Spring Security特性

身份验证(Authentication):Spring Security提供了多种身份验证机制,包括基于表单、HTTP基本认证、OpenID、LDAP、OAuth等。它还支持自定义身份验证逻辑,可以轻松地集成其他身份验证提供者。

授权(Authorization):Spring Security提供了强大的授权机制,可以根据用户的身份和角色来限制其对资源的访问。它支持基于角色和权限的访问控制,可以在代码和配置中定义细粒度的安全规则。

攻击防护(Attack Protection):Spring Security提供了多种防护机制,用于防范常见的安全威胁,如跨站脚本攻击(XSS)、跨站请求伪造(CSRF)、点击劫持、会话管理等。它使用了各种技术和策略,如CSRF令牌、XSS过滤器、会话管理器等来保护应用程序的安全性。

安全事件和日志(Security Events and Logging):Spring Security提供了丰富的安全事件和日志功能,可以记录和跟踪与安全相关的事件。开发者可以基于这些事件和日志来监控和审计应用程序的安全性,并对可能的安全威胁做出响应。

扩展性和定制化(Extensibility and Customization):Spring Security提供了灵活的配置选项和扩展机制,使开发者能够根据应用程序的特定需求进行定制。开发者可以编写自定义的认证和授权逻辑,实现自定义的安全过滤器和拦截器,以满足应用程序的特定安全需求。

本文将着重介绍身份验证、授权的特性。

二、Spring Security代码编写:第一阶段

1. 创建Maven项目

在这里插入图片描述

2. 在pom文件里添加依赖

    <dependencies>
        <!-- SpringBoot -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-dependencies</artifactId>
            <version>2.1.10.RELEASE</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>
        <!-- SpringMVC -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
            <version>2.1.10.RELEASE</version>
        </dependency>
        <!-- Thymeleaf -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-thymeleaf</artifactId>
            <version>2.1.10.RELEASE</version>
        </dependency>
        <!--Spring Security-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-security</artifactId>
            <version>2.1.10.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.18.24</version>
            <scope>compile</scope>
        </dependency>
        <dependency>
            <groupId>io.jsonwebtoken</groupId>
            <artifactId>jjwt</artifactId>
            <version>0.7.0</version>
        </dependency>
        <!--json-->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>fastjson</artifactId>
            <version>1.2.60</version>
            <scope>compile</scope>
        </dependency>
    </dependencies>

3. 目录结构

在这里插入图片描述

4. SecurityController文件

@Controller
public class SecurityController {
    @RequestMapping("/main")
    public String main(){
        return "main";
    }
}

5. 配置SpringBootMain文件

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

6. application.yml文件

server:
  port: 8181

spring:
  datasource:
    driver-class-name: com.mysql.cj.jdbc.Driver
    username: root
    password:
    url: jdbc:mysql://localhost:3308/security

7. main.html文件

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>main</title>
</head>
<body>
    <h1>我是Main页面!我要刺杀老师!喝啊!</h1>
    <a href="/logout">退出登录</a>
</body>
</html>

8. 启动项目

打开网页,输入:127.0.0.1:8080
做一次页面点击后,控制台输出密码
在这里插入图片描述
我们输入固定的用户名:user与密码:891de0f8-256c-4f74-ba5b-999f25531c82可进行登录,登录后在地址栏可以访问/main页面
在这里插入图片描述
在这里插入图片描述
没有登录前,会自动跳转到/login页面,因为没有做登录之前,程序不让进行其他操作(第二阶段可改)
我们其实登录都是使用自定义的用户名和密码,于是乎,我们如何自定义用户名、密码呢?且听下回分解

三、Spring Security代码编写:第二阶段

欸!我就是下回诶!

1. 第二阶段第三阶段总体结构图

在这里插入图片描述

2. 在pom文件里添加依赖

        <!-- 4.添加mysql数据库的驱动包依赖-->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>8.0.30</version>
        </dependency>
        <!-- 3.添加Mybatis 的启动器依赖-->
        <dependency>
            <groupId>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter</artifactId>
            <version>2.1.1</version>
        </dependency>

3. SecurityConfig文件

package com.jjy.config;

import com.jjy.service.impl.UserDetailsServiceImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.authentication.rememberme.PersistentTokenRepository;

@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        // 表单认证
        http.formLogin()
                .loginProcessingUrl("/login")
                //此处表单不写action属性也可以  //当发现/login时认为是登录,需要执行UserDetailsServiceImpl
                .successForwardUrl("/main")   //此处是post请求
                .loginPage("/login.html");

        // url 拦截
        http.authorizeRequests()
                .antMatchers("/login.html").permitAll() //login.html不需要被认证
                .anyRequest().authenticated();//所有的请求都必须被认证。必须登录后才能访问。

        //关闭csrf防护
        http.csrf().disable();
    }
    @Bean // 是Bean标签,security框架要求密码必须是加密的处理,
    public PasswordEncoder getPwdEncoder(){
        return new BCryptPasswordEncoder();
    }
}

4. UserDetailsServiceImpl文件

自定义用户名为admin,密码为123

package com.jjy.service.impl;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.authority.AuthorityUtils;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;

@Service
public class UserDetailsServiceImpl implements UserDetailsService {
    @Autowired
    private PasswordEncoder passwordEncoder;
    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        // 1. 查询数据库判断用户名是否存在,如果不存在抛出UsernameNotFoundException
        if (!username.equals("admin")){
            throw new UsernameNotFoundException("用户名不存在");
        }
        // 把查询出来的密码进行解析,或者直接把password放到构造方法中
        String password = passwordEncoder.encode("123");
        return new User(username, password, AuthorityUtils.commaSeparatedStringToAuthorityList("admin"));

    }
}

5. login.html文件

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<form action="/login" method="post">
    用户名:<input type="text" name="username"><br/>
    密码:<input type="password" name="password"><br/>
    <input type="submit" value="提交">
</form>
</body>
</html>

6. 实现效果

在这里插入图片描述

四、Spring Security代码编写:第三阶段

记忆功能实现

1. RememberMeConfig文件

package com.jjy.config;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.web.authentication.rememberme.JdbcTokenRepositoryImpl;
import org.springframework.security.web.authentication.rememberme.PersistentTokenRepository;
import javax.sql.DataSource;
@Configuration
public class RememberMeConfig {
    @Autowired
    private DataSource dataSource;
    @Bean
    public PersistentTokenRepository getPersistentTokenRepository() {
        JdbcTokenRepositoryImpl jdbcTokenRepositoryImpl=new JdbcTokenRepositoryImpl();
        jdbcTokenRepositoryImpl.setDataSource(dataSource);
        //自动建表,第一次启动时需要,第二次启动时注释掉
        //jdbcTokenRepositoryImpl.setCreateTableOnStartup(true);  //该代码不好用,使用sql手动创建库,表
        return jdbcTokenRepositoryImpl;
    }
}

2. SecurityConfig文件

package com.jjy.config;

import com.jjy.service.impl.UserDetailsServiceImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.authentication.rememberme.PersistentTokenRepository;

@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {


    @Autowired
    PersistentTokenRepository repository;
    // private  RememberMeConfig repository;

    @Autowired
    private UserDetailsServiceImpl userDetailsService;


    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.rememberMe()
                .userDetailsService(userDetailsService) //登录逻辑交给哪个对象
                .tokenRepository(repository);   //持久层对象
        // 表单认证
        http.formLogin()
                .loginProcessingUrl("/login")
                //此处表单不写action属性也可以  //当发现/login时认为是登录,需要执行UserDetailsServiceImpl
                .successForwardUrl("/main")   //此处是post请求
                .loginPage("/login.html");

        // url 拦截
        http.authorizeRequests()
                .antMatchers("/login.html").permitAll() //login.html不需要被认证
                .anyRequest().authenticated();//所有的请求都必须被认证。必须登录后才能访问。

        //关闭csrf防护
        http.csrf().disable();
    }

    @Bean // 是Bean标签,security框架要求密码必须是加密的处理,
    public PasswordEncoder getPwdEncoder(){
        return new BCryptPasswordEncoder();
    }
}

3. login.html更改

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<form action="/login" method="post">
    用户名:<input type="text" name="username"><br/>
    密码:<input type="password" name="password"><br/>
    <input type="checkbox" name="remember-me" value="true"/>记住我 <br/>
    <input type="submit" value="提交">
</form>
</body>
</html>

4. 创建数据库和表

创建security数据库
创建表的语句

create table persistent_logins (
username varchar(64) not null, 
series varchar(64) primary key, 
token varchar(64) not null, 
last_used timestamp not null)

5. 实现效果

输入如下属性,点击记住我(密码123),之后提交
在这里插入图片描述
可以自动跳转页面,同时数据库新增一条数据
在这里插入图片描述
点击退出登录后,数据库内数据被清除
在这里插入图片描述

五、Spring Security代码编写:第四阶段

本阶段主要做权限验证

1. 项目结构

在这里插入图片描述

2. 在pom文件里添加依赖

        <dependency>
            <groupId>org.thymeleaf.extras</groupId>
            <artifactId>thymeleaf-extras-springsecurity5</artifactId>
            <version>3.0.4.RELEASE</version>
        </dependency>

3. 新增show.html界面

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"
      xmlns:th="http://www.thymeleaf.org"
      xmlns:sec="http://www.thymeleaf.org/thymeleaf-extras-springsecurity5">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<h1>获得springsequraty属性</h1>
用户名:<span sec:authentication="name">123</span><br/>
用户名:<span sec:authentication="principal.username">456</span><br/>
凭证:<span sec:authentication="credentials">456</span><br/>
权限和角色:<span sec:authentication="authorities">456</span><br/>
客户端地址:<span sec:authentication="details.remoteAddress">456</span><br/>
sessionId:<span sec:authentication="details.sessionId">456</span><br/>

通过权限判断:
<button sec:authorize="hasAuthority('/insert')">新增</button>
<button sec:authorize="hasAuthority('/delete')">删除</button>
<button sec:authorize="hasAuthority('/update')">修改</button>
<button sec:authorize="hasAuthority('/select')">查看</button>
<br/>
通过角色判断:
<button sec:authorize="hasRole('abc')">新增</button>
<button sec:authorize="hasRole('abc')">删除</button>
<button sec:authorize="hasRole('abc')">修改</button>
<button sec:authorize="hasRole('abc1')">查看</button>
</body>
</html>

4. 更新UserDetailsServiceImpl文件返回值

	return new User(username, password, AuthorityUtils.commaSeparatedStringToAuthorityList("admin,/select,/insert,ROLE_abc1"));

在这里插入图片描述
赋予admin用户select、insert的权限,归于ROLE_abc1组下

5. 实现效果

登录后,我们通过地址栏输入http://127.0.0.1:8181/show进入show页面,可以发现,用户admin的权限只有新增、查看两项。
在这里插入图片描述

六、CSRF

CSRF(Cross-Site Request Forgery,跨站请求伪造)是一种常见的网络攻击技术,攻击者通过伪造用户的请求来实现非法操作,利用用户在目标网站上的身份和权限。

CSRF攻击通常发生在存在用户身份验证的应用程序中。攻击者诱使受害者在已经登录过的网站上执行恶意操作,从而利用受害者的权限进行非法操作。攻击者可以通过各种手段,如发送伪造的电子邮件、社交工程攻击、恶意广告等来引诱受害者点击恶意链接或访问恶意网站。

Spring Security是一个功能强大的安全框架,提供了多种功能来保护应用程序免受常见的安全威胁,包括 CSRF攻击。在Spring Security中,默认情况下启用了CSRF防护。

CSRF防护是通过生成和验证一个CSRF令牌来实现的。这个令牌通常是一个随机生成的字符串,由服务器在用户访问页面时生成,并将其附加到表单或请求的头部中。在用户提交请求时,服务器会验证请求中的令牌是否与服务器生成的令牌匹配,如果不匹配,服务器将拒绝该请求,防止CSRF攻击的发生。

在Spring Security配置中,可以使用csrf()方法来配置和启用CSRF防护。默认情况下,Spring Security会生成一个CSRF令牌,并将其附加到表单和请求头中。如果需要关闭CSRF防护,可以使用http.csrf().disable()方法来禁用它。

总结起来,CSRF是一种常见的网络攻击技术,Spring Security提供了默认的CSRF防护来保护应用程序免受此类攻击。


总结

本文讲述了:
Spring Security:进行身份验证、授权功能的框架
在下攸攸太上,如果把我的生活拍成电视剧,那将会是《来自行星的高级生命体》。

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

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

相关文章

SkyWalking 环境搭建部署

架构简介 skywalking agent : 和业务系统绑定在一起,负责收集各种监控数据skywalking oapservice : 是负责处理监控数据的,比如接受skywalking agent的监控数据,并存储在数据库中;接受skywalking webapp的前端请求,从数据库查询数据,并返回数据给前端。Skywalking oapserv…

前端开发之装饰器模式

介绍 装饰器模式 是在不修改对象内部结构的情况下&#xff0c;动态地给对象添加功能的一种设计模式。在软件开发中&#xff0c;有时候我们需要为已有对象添加一些额外的行为&#xff0c;但不希望修改该对象的代码&#xff0c;装饰器模式可以很好的满足这一需求。 在TypeScrip…

C++3D迷宫

目录 开头程序程序的流程图程序游玩的效果下一篇博客要说的东西 开头 大家好&#xff0c;我叫这是我58。 程序 #include <iostream> using namespace std; void printmaze(char strmaze[5][5][5]) {cout << "-----" << endl;int i 0;int ia 0…

Qt优秀开源项目之二十三:QSimpleUpdater

QSimpleUpdater是开源的自动升级模块&#xff0c;用于检测、下载和安装更新。 github地址&#xff1a;https://github.com/alex-spataru/QSimpleUpdater QSimpleUpdater目前Star不多&#xff08;911个&#xff09;&#xff0c;但已在很多开源项目看到其身影&#xff0c;比如Not…

Chunk-based Chinese Spelling Check with Global Optimization(EMNLP2020)

Chunk-based Chinese Spelling Check with Global Optimization(EMNLP2020) 一.概述 作者认为&#xff0c;一方面&#xff0c;以往的工作大多只考虑对汉字读音或字形相近的错字进行校正&#xff0c;而没有对视觉上和语音上不相关的错字进行校正&#xff1b;另一方面&#xff0…

使用 Nuxt Kit 的构建器 API 来扩展配置

title: 使用 Nuxt Kit 的构建器 API 来扩展配置 date: 2024/9/24 updated: 2024/9/24 author: cmdragon excerpt: 摘要:本文详细介绍了如何使用 Nuxt Kit 的构建器 API 来扩展和定制 Nuxt 3 项目的 webpack 和 Vite 构建配置,包括扩展Webpack和Vite配置、添加自定义插件、…

nginx如何拦截未经授权的跳转

nginx如何拦截未经授权的跳转 背景准备好一个网站准备好引用网站配置nginx拦截效果 背景 在现实工作中往往有一些企业或人未取得授权但是转载或挂载我们的网址。那么有些要求严格或者有其他原因的情况下不希望这些链接正常访问。所以就有了这样的需求。前提是咱们的网站什么的是…

如何把python(.py或.ipynb)文件打包成可运行的.exe文件?

将 Python 程序打包成可执行的 .exe 文件&#xff0c;通常使用工具如 PyInstaller。这是一个常用的 Python 打包工具&#xff0c;可以将 Python 程序打包成独立的可执行文件&#xff0c;即使没有安装 Python 也能运行。 步骤&#xff1a; 1. 安装 PyInstaller 使用 conda 安…

速通LLaMA3:《The Llama 3 Herd of Models》全文解读

文章目录 概览论文开篇IntroductionGeneral OverviewPre-TrainingPre-Training DataModel ArchitectureInfrastructure, Scaling, and EfficiencyTraining Recipe Post-TrainingResultsVision ExperimentsSpeech Experiments⭐Related WorkConclusionLlama 3 模型中的数学原理1…

docker搭建个人网盘,支持多种格式,还能画图,一键部署

1&#xff09;效果 2&#xff09;步骤 2.1&#xff09;docker安装 docker脚本 bash <(curl -sSL https://cdn.jsdelivr.net/gh/SuperManito/LinuxMirrorsmain/DockerInstallation.sh)docker-compose脚本 curl -L "https://github.com/docker/compose/releases/late…

【计网】从零开始掌握序列化 --- 实现网络计算器项目

​​​请各位保持头脑清醒&#xff0c; ​​​读些好书&#xff0c;做点有用的事&#xff0c; ​​​快快乐乐地生活。 ​​​ --- 斯蒂芬金 《肖申克的救赎》--- 从零开始掌握序列化 1 知识回顾2 服务器框架3 客户端框架4 运行测试 1 知识回顾 前面两篇文章学习中基础知识…

蓝队技能-应急响应篇Web内存马查杀JVM分析Class提取诊断反编译日志定性

知识点&#xff1a; 1、应急响应-Web内存马-定性&排查 2、应急响应-Web内存马-分析&日志 注&#xff1a;传统WEB类型的内存马只要网站重启后就清除了。 演示案例-蓝队技能-JAVA Web内存马-JVM分析&日志URL&内存查杀 0、环境搭建 参考地址&#xff1a;http…

常见统计量与其抽样分布

什么是统计量 我们首先给出统计量的定义:设 X 1 , X 2 , ⋯ , X n X_1,X_2,\cdots,X_n X1​,X2​,⋯,Xn​ 为来自于总体X的一个样本&#xff0c; g ( X 1 , X 2 , ⋯ , X n ) g(X_1,X_2,\cdots,X_n) g(X1​,X2​,⋯,Xn​) 为关于 X 1 , X 2 , ⋯ , X n X_1,X_2,\cdots,X_n X…

Python | Leetcode Python题解之第434题字符串中的单词数

题目&#xff1a; 题解&#xff1a; class Solution:def countSegments(self, s):segment_count 0for i in range(len(s)):if (i 0 or s[i - 1] ) and s[i] ! :segment_count 1return segment_count

【JS】严格模式/非严格模式的区别

JS的严格模式和非严格模式 js运行有两种模式&#xff1a;一种是普通模式&#xff1b;一种是严格模式。 严格模式是ES5添加的&#xff0c;是比普通模式多一部分的js规则。如果在ES5之前js解析引擎&#xff0c;会忽略严格模式。 js一般默认是普通模式&#xff0c;ES6的模块和Cla…

数据结构 ——— 数组 nums 包含了从 0 到 n 的所有整数,但是其中缺失了一个,请编写代码找出缺失的整数,并且在O(N)时间内完成

目录 题目要求 代码实现 方法1&#xff08;异或法&#xff09;&#xff1a; 异或算法的时间复杂度&#xff1a; 方法2&#xff08;等差数列公式&#xff09;&#xff1a; 等差数列公式的时间复杂度&#xff1a; 题目要求 整型数组 nums 包含了从 0 到 n 的所有整数&…

VPN概述

目录 定义&#xff1a; VPN的分类 VPN的主要应用场景 GRE VPN概念 GRE VPN的优缺点 GRE VPN应用场景和配置 GRE VPN配置流程 Router A&#xff1a; Router B&#xff1a; 定义&#xff1a; 虚拟专用网络(VPN)是一种通过公用网络线路建立私有网络&#xff0c;用于传输私…

UE学习篇ContentExample解读------Blueprint_Communication-上

文章目录 总览描述批次阅览1.1 Basic communication with a target blueprint1.2 Basic communication via actor casting1.3 Blueprint communication via actor casting to child Blueprint1.4 Communicating with all actors of a specific class 概念总结致谢&#xff1a; …

VulnHub-Narak靶机笔记

Narak靶机笔记 概述 Narak是一台Vulnhub的靶机&#xff0c;其中有简单的tftp和webdav的利用&#xff0c;以及motd文件的一些知识 靶机地址&#xff1a; https://pan.baidu.com/s/1PbPrGJQHxsvGYrAN1k1New?pwda7kv 提取码: a7kv 当然你也可以去Vulnhub官网下载 一、nmap扫…

【专题】2024年中国白酒行业数字化转型研究报告合集PDF分享(附原数据表)

原文链接&#xff1a;https://tecdat.cn/?p37755 消费人群趋于年轻化&#xff0c;消费需求迈向健康化&#xff0c;消费场景与渠道走向多元化&#xff0c;这些因素共同驱动企业凭借数据能力来适应市场的变化。从消费市场来看&#xff0c;消费群体、需求、场景及渠道皆展现出与…