SpringBoot security 安全认证(一)——登录验证

本节内容:使用springboot自动security模块实现用户登录验证功能;
登录过程如下图:
在这里插入图片描述
AuthenticationManager内容实现用户账号密码验证,还可以对用户状态(启用/禁用),逻辑删除,账号是否被锁定等判断。密码加密方式内置了好几种,我使用的是BCryptPasswordEncoder。那么我们在用户注册时密码要使用 new BCryptPasswordEncoder().encode(pwd)进行加密。

代码实现过程:
1、引入相关依赖;
2、创建UserDetails实现类LoginUser;
3、创建UserDetailsService实现类UserDetailsServiceImpl;
4、SecurityConfiguration配置,将UserDetailsServiceImpl注入相关对象,并配置加密算法;
5、实现账号密码验证;

pom.xml引入依赖

<dependencies><!-- 实现对 Spring MVC 的自动化配置 --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><!-- spring security 安全认证 --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-security</artifactId></dependency><!-- Token生成与解析--><dependency><groupId>io.jsonwebtoken</groupId><artifactId>jjwt</artifactId><version>0.9.1</version></dependency><!-- 解析客户端操作系统、浏览器等 --><dependency><groupId>eu.bitwalker</groupId><artifactId>UserAgentUtils</artifactId><version>1.21</version></dependency>
<!-- String工具类 --><dependency><groupId>org.apache.commons</groupId><artifactId>commons-lang3</artifactId><version>3.12.0</version></dependency><!-- 阿里JSON解析器 --><dependency><groupId>com.alibaba.fastjson2</groupId><artifactId>fastjson2</artifactId><version>2.0.34</version></dependency><!-- 方便等会写单元测试 --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency><dependency><groupId>junit</groupId><artifactId>junit</artifactId><version>4.12</version><scope>test</scope></dependency><!-- 引入 Swagger 依赖 --><dependency><groupId>io.springfox</groupId><artifactId>springfox-swagger2</artifactId><version>2.9.2</version></dependency><!-- 引入 Swagger UI 依赖,以实现 API 接口的 UI 界面 --><dependency><groupId>io.springfox</groupId><artifactId>springfox-swagger-ui</artifactId><version>2.9.2</version></dependency></dependencies>

UserDetails的实现类LoginUser

是数据库用户到Spring用户的转换,提供给Spring内部获取用户账号、状态等的。

package com.luo.chengrui.labs.lab04.model;import com.alibaba.fastjson2.annotation.JSONField;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;import java.util.Collection;/*** 登录用户身份权限** @author ruoyi*/
public class LoginUser implements UserDetails {private static final long serialVersionUID = 1L;/*** 用户ID*/private String userId;/*** 用户唯一标识*/private String token;/*** 登录时间*/private Long loginTime;/*** 过期时间*/private Long expireTime;/*** 登录IP地址*/private String ipaddr;/*** 登录地点*/private String loginLocation;/*** 浏览器类型*/private String browser;/*** 操作系统*/private String os;//数据库用户映射表private SysUser user;public LoginUser(String userId, SysUser user) {this.userId = userId;this.user = user;}public static long getSerialVersionUID() {return serialVersionUID;}public String getUserId() {return userId;}public void setUserId(String userId) {this.userId = userId;}public String getToken() {return token;}public void setToken(String token) {this.token = token;}public Long getLoginTime() {return loginTime;}public void setLoginTime(Long loginTime) {this.loginTime = loginTime;}public Long getExpireTime() {return expireTime;}public void setExpireTime(Long expireTime) {this.expireTime = expireTime;}public String getIpaddr() {return ipaddr;}public void setIpaddr(String ipaddr) {this.ipaddr = ipaddr;}public String getLoginLocation() {return loginLocation;}public void setLoginLocation(String loginLocation) {this.loginLocation = loginLocation;}public String getBrowser() {return browser;}public void setBrowser(String browser) {this.browser = browser;}public String getOs() {return os;}public void setOs(String os) {this.os = os;}@Overridepublic Collection<? extends GrantedAuthority> getAuthorities() {return null;}@JSONField(serialize = false)@Overridepublic String getPassword() {return user.getPassword();}@Overridepublic String getUsername() {return user.getUsername();}//账号未过期 @JSONField(serialize = false)@Overridepublic boolean isAccountNonExpired() {return true;}//账号未被锁定@JSONField(serialize = false)@Overridepublic boolean isAccountNonLocked() {return true;}//密码未过期@JSONField(serialize = false)@Overridepublic boolean isCredentialsNonExpired() {return true;}/*** 是否可用 ,禁用的用户不能身份验证** @return*/@JSONField(serialize = false)@Overridepublic boolean isEnabled() {return true;}
}

LoginUser类看着字段较多,基本都是和业务相关,比如记录登录用户的IP,地址,登录时间等的。看实际情况,可以优化掉的,仅保留SysUser对象也是完全可以的。

UserDetailsService接口实现类 UserDetailsServiceImpl

实现根据用户名获取用户信息,提供给spring内部调用的。

package com.luo.chengrui.labs.lab04.service;import com.luo.chengrui.labs.lab04.model.LoginUser;
import com.luo.chengrui.labs.lab04.model.SysUser;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;import java.util.Objects;/*** 用户验证处理** @author ruoyi*/
@Service
public class UserDetailsServiceImpl implements UserDetailsService {private static final Logger log = LoggerFactory.getLogger(UserDetailsServiceImpl.class);@Autowiredprivate UserService userService;@Overridepublic UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {SysUser user = userService.selectUserByUserName(username);if (user == null) {log.info("登录用户:{} 不存在.", username);throw new RuntimeException("登录用户:" + username + " 不存在");} else if (Objects.equals(1, user.getDelFlag())) {log.info("登录用户:{} 已被删除.", username);throw new RuntimeException("对不起,您的账号:" + username + " 已被删除");} else if (Objects.equals(0, user.getStatus())) {log.info("登录用户:{} 已被停用.", username);throw new RuntimeException ("对不起,您的账号:" + username + " 已停用");}return createLoginUser(user);}public UserDetails createLoginUser(SysUser user) {return new LoginUser(user.getUserId(),user);}
}

1、以上判断用户状态和是否被删除等操作也可以交由spring去做,你只要在LoginUser类中相关方法中返回结果即可。在这里可以做额外的合法性判断。(如这个账号登录次数超限了,并且可以提示相关登录失败信息)
2、实现了根据用户账号查询用户信息方法,最后返回了我们上面定义的LoginUser对象。

LoginUservice登录实现

package com.luo.chengrui.labs.lab04.service;import com.luo.chengrui.labs.lab04.model.LoginUser;
import com.luo.chengrui.labs.lab04.utils.UUID;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.stereotype.Service;import javax.annotation.Resource;
import java.util.HashMap;
import java.util.Map;/*** @author* @version 1.0.0* @description* @createTime 2024/01/05*/
@Service
public class LoginService {@Resourceprivate AuthenticationManager authenticationManager;private static final String secret = "abcdefghijklmnopqrstuvwxyz";public String login(String username, String password) {// 用户验证Authentication authentication = null;try {UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(username, password);authentication = authenticationManager.authenticate(authenticationToken);} catch (Exception e) {//这里应该按不同异常类型分别捕获,更精确的提示用户登录失败的原因。看业务需要throw new RuntimeException("用户名或密码错误");} finally {}LoginUser loginUser = (LoginUser) authentication.getPrincipal();// 生成tokenreturn createToken(loginUser);}/*** 创建令牌** @param loginUser 用户信息* @return 令牌*/public String createToken(LoginUser loginUser) {String token = UUID.fastUUID().toString();loginUser.setToken(token);Map<String, Object> claims = new HashMap<>();claims.put("LOGIN_USER_KEY", token);return createToken(claims);}private String createToken(Map<String, Object> claims) {String token = Jwts.builder().setClaims(claims).signWith(SignatureAlgorithm.HS512, secret).compact();return token;}/*** 刷新令牌有效期,是指刷新缓存中存储的token信息。我们本示例中暂不做缓存。** @param loginUser 登录信息*/public void refreshToken(LoginUser loginUser) {loginUser.setLoginTime(System.currentTimeMillis());loginUser.setExpireTime(loginUser.getLoginTime() + 30 * 60 * 1000);}
}

SecurityConfig

1、创建鉴权管理器:AuthenticationManager ;
2、设置请求过滤;
3、设置密码加密算法;
4、设置用户获取对象;

package com.luo.chengrui.labs.lab04.config;import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.http.HttpMethod;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.web.filter.CorsFilter;/*** spring security配置** @author */
@EnableGlobalMethodSecurity(prePostEnabled = true, securedEnabled = true)
public class SecurityConfig extends WebSecurityConfigurerAdapter {/*** 自定义用户认证逻辑*/@Autowiredprivate UserDetailsService userDetailsService;/*** 解决 无法直接注入 AuthenticationManager** @return* @throws Exception*/@Bean@Overridepublic AuthenticationManager authenticationManagerBean() throws Exception {return super.authenticationManagerBean();}/*** anyRequest          |   匹配所有请求路径*/@Overrideprotected void configure(HttpSecurity httpSecurity) throws Exception {httpSecurity// CSRF禁用,因为不使用session.csrf().disable()// 过滤请求.authorizeRequests()// 所有请求均以放行.anyRequest().permitAll().and().headers().frameOptions().disable();}/*** 强散列哈希加密实现*/@Beanpublic BCryptPasswordEncoder bCryptPasswordEncoder() {return new BCryptPasswordEncoder();}/*** 设置密码加密算法*/@Overrideprotected void configure(AuthenticationManagerBuilder auth) throws Exception {auth.userDetailsService(userDetailsService).passwordEncoder(bCryptPasswordEncoder());}
}

到此,使用Spring security登录验证的核心代码就写完了。再一个实现UserService类实现从数据库查询用户

UserServiceImpl

package com.luo.chengrui.labs.lab04.service;import com.luo.chengrui.labs.lab04.model.SysUser;
import com.luo.chengrui.labs.lab04.utils.SecurityUtils;
import com.luo.chengrui.labs.lab04.utils.StringUtils;
import org.springframework.stereotype.Service;import java.util.*;
import java.util.stream.Collectors;/*** @author* @version 1.0.0* @description* @createTime 2024/01/31*/
@Service
public class UserService {private static final Map<String, SysUser> userMap = new HashMap<>();static {userMap.put("admin", new SysUser("1", "admin", SecurityUtils.encryptPassword("admin123"), 1));}public List<SysUser> selectUser() {return userMap.entrySet().stream().map(item -> item.getValue()).collect(Collectors.toList());}public SysUser selectUserByUserName(String username) {SysUser user = userMap.get(username);if (user == null) {throw new RuntimeException("用户不存在");}return user;}public SysUser registerUser(SysUser user) {if (user == null) {throw new RuntimeException("用户信息不能为空");}if (StringUtils.isEmpty(user.getUsername())) {throw new RuntimeException("用户名不能为空");}if (StringUtils.isEmpty(user.getPassword())) {throw new RuntimeException("密码不能为空");}if (userMap.get(user.getUsername()) != null) {throw new RuntimeException("用户名已经存在");}user.setUserId(UUID.randomUUID().toString());user.setStatus(1);user.setPassword(SecurityUtils.encryptPassword(user.getPassword()));userMap.put(user.getUserId(), user);return user;}public SysUser selectUser(String username) {return userMap.get(username);}
}

简单模拟了根据账号查询用户的接口,实际是事先在userMap中放了一个admin用户而已。

SysUser数据库对象

package com.luo.chengrui.labs.lab04.model;/*** @author* @version 1.0.0* @description* @createTime 2024/01/31*/
public class SysUser {private String userId;private String username;private String password;private Integer delFlag;private Integer status;public SysUser() {}public SysUser(String userId, String username, String password,  Integer status) {this.userId = userId;this.username = username;this.password = password;this.status = status;}public String getUserId() {return userId;}public void setUserId(String userId) {this.userId = userId;}public String getUsername() {return username;}public void setUsername(String username) {this.username = username;}public String getPassword() {return password;}public void setPassword(String password) {this.password = password;}public Integer getDelFlag() {return delFlag;}public void setDelFlag(Integer delFlag) {this.delFlag = delFlag;}public Integer getStatus() {return status;}public void setStatus(Integer status) {this.status = status;}
}

controller

package com.luo.chengrui.labs.lab04.controller;import com.luo.chengrui.labs.lab04.model.AjaxResult;
import com.luo.chengrui.labs.lab04.model.LoginBody;
import com.luo.chengrui.labs.lab04.service.LoginService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;/*** @author* @version 1.0.0* @description* @createTime 2023/07/17*/
@RestController
@Api(tags = "用户 API 接口")
public class LoginController {@AutowiredLoginService loginService;@ApiOperation(value = "用户登录 ", notes = "目前仅仅是作为测试,所以返回用户全列表")@PostMapping("/login")public AjaxResult login(@RequestBody LoginBody loginBody) {AjaxResult ajax = AjaxResult.success();// 生成令牌String token = loginService.login(loginBody.getUsername(), loginBody.getPassword());ajax.put("token", token);return ajax;}}

swagger配置

package com.luo.chengrui.labs.lab04.config;import com.luo.chengrui.labs.lab04.service.TokenService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import springfox.documentation.builders.ApiInfoBuilder;
import springfox.documentation.builders.ParameterBuilder;
import springfox.documentation.builders.PathSelectors;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.schema.ModelRef;
import springfox.documentation.service.ApiInfo;
import springfox.documentation.service.Contact;
import springfox.documentation.service.Parameter;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.swagger2.annotations.EnableSwagger2;import java.util.ArrayList;
import java.util.List;/*** 访问地址:/swagger-ui.html** @author* @version 1.0.0* @description* @createTime 2023/07/17*/
@Configuration
@EnableSwagger2
public class SwaggerConfiguration {@AutowiredTokenService tokenService;@Beanpublic Docket createRestApi() {/* 让swagger页面上的每个接口都添加一个Header参数,用来传递token参数*/ParameterBuilder ticketPar = new ParameterBuilder();List<Parameter> pars = new ArrayList<Parameter>();ticketPar.name(tokenService.getHeader()).description("user ticket")//Token 以及Authorization 为自定义的参数,session保存的名字是哪个就可以写成那个.modelRef(new ModelRef("string")).parameterType("header").required(false).build(); //header中的ticket参数非必填,传空也可以pars.add(ticketPar.build()); //根据每个方法名也知道当前方法在设置什么参数// 创建 Docket 对象return new Docket(DocumentationType.SWAGGER_2) // 文档类型,使用 Swagger2.apiInfo(this.apiInfo()) // 设置 API 信息// 扫描 Controller 包路径,获得 API 接口.select().apis(RequestHandlerSelectors.basePackage("com.luo.chengrui.labs.lab04.controller")).paths(PathSelectors.any())// 构建出 Docket 对象.build().globalOperationParameters(pars);}/*** 创建 API 信息*/private ApiInfo apiInfo() {return new ApiInfoBuilder().title("测试接口文档示例").description("我是一段描述").version("1.0.0") // 版本号.contact(new Contact("XX", "http://localhost", "luodz@gmail.com")) // 联系人.build();}
}

Swaager请求示例:
在这里插入图片描述
响应结果:
在这里插入图片描述

后台方法调用:
1、调用 UserDetailsServiceImpl.LoadUserByUsername方法,获取用户信息;
在这里插入图片描述

2、判断用户各种可用状态和密码合法性。
在这里插入图片描述
小结:本节主要演示了如何使用Spring去实现登录验证
1、创建UserDetails接口实现类,UserDetails是Spring内部定义的登录用户信息,包含账号、密码、删除状态、禁用状态、锁定状态、密码过期状态;
2、创建UserDetailsService接口实现类,实现loadUserByUsername(String username)方法;
3、用户合法性验证,仅一行代码即可完成用户合法性验证:

Authentication authentication = authenticationManager.authenticate(new UsernamePasswordAuthenticationToken(username, password));
LoginUser loginUser = (LoginUser) authentication.getPrincipal();

下一节,咱们可以实现对接口访问的拦截了。

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

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

相关文章

LeetCode.189. 轮转数组

题目 题目链接 分析 首先能想到的就是可以用一个新数组&#xff0c;先保存原数组的后 k 个元素&#xff0c;再保存原数组的前 n−k 个元素。但题目要求不使用额外的数组空间&#xff0c;那么就需要在原数组上做操作。 我们可以先把整个数组翻转一下&#xff0c;这样后半段元…

虚幻UE5Matehuman定制自己的虚拟人,从相机拍照到UE5制作全流程

开启自己的元宇宙,照片扫描真实的人类,生成虚拟形象,保姆级教程,欢迎大家指正。 需要的软件: 制作流程: 一.拍照。 围绕自己拍照,大概20多张图就差不多了,把脑门漏出来,无需拍后脑勺。 拍照方式 例如,拍照时尽量不要在脸上体现出明显的光源方向。

07. 【Linux教程】远程登录

Linux 远程登录 前面介绍了如何安装 Linux 终端工具&#xff0c;本小节介绍本地电脑如何使用 ssh 命令远程登录、Linux 终端工具远程登录的方式&#xff0c;这两种登录方式都是基于 ssh 网络安全协议的&#xff0c;学会使用远程登录 Linux 服务器&#xff0c;会让你对 Linux 系…

Postman(接口测试工具),什么是Postman接口

目录 一.基本介绍 Postman 是什么Postman 快速入门快速入门需求说明 二.Postman 完成 Controller 层测试 需要的代码&#xff1a; Java类request.jspsuccess.jsp1. 完成请求2. 完成请求3. 完成请求4. 完成请求5. 完成请求 三.发送join 目录 一.基本介绍 Postman 是什么 …

使用 Dockerfile 定制镜像详解

使用 Dockerfile 定制镜像详解 1.DockerfileFROM 指定基础镜像RUN 执行命令构建镜像 2.COPY 复制文件3.ADD 更高级的复制文件4.CMD 容器启动命令5.ENTRYPOINT 入口点6.ENV 设置环境变量7.ARG 构建参数8.VOLUME 定义匿名卷9.EXPOSE 暴露端口10.WORKDIR 指定工作目录11.USER 指定…

通过Netbackup恢复Oracle备份实操手册

1、系统环境描述 1 2、恢复前数据备份 2 2.1 在NBU上执行一次完整的备份 2 2.2 查看ORACLE的备份集 3 2.2.1在备份客户端上查看备份集 3 2.2.2在备份服务器netbackup上查看客户端备份集 4 3、本机恢复方法 5 3.1丢失SPFILE文件恢复方法 5 3.2丢失CONTROLFILE文件恢复方…

51单片机编程应用(C语言):模块化编程

下面我们模块化几个函数&#xff1a; Delay.c //延时子函数 void Delay(unsigned int xms) {unsigned char i, j;while(xms--){i 2;j 239;do{while (--j);} while (--i);} } Delay.h #ifndef __DELAY_H__ #define __DELAY_H__void Delay(unsigned int xms);#endifNixie.h …

js 设置、获取、删除标签属性以及H5自定义属性

1. 设置标签属性 使用setAttribute()(‘属性名’, ‘属性值’)方法可以添加、修改、删除属性。   下面的demo是为input添加、修改、删除value属性&#xff1a; 1.1. HTML <input type"text" class"input"> <input type"text" class…

有没有合适写毕业论文的AI工具?

最近挺多同学在忙着写毕业论文&#xff0c;不断在“提交-打回-修改-提交”过程里循环着&#xff0c;好不容易写完了&#xff0c;还得考虑论文查重的问题&#xff01;基哥作为一名曾经的毕业生&#xff0c;当然也体验过这种痛苦了。 但是&#xff0c;大人&#xff0c;时代变了&…

无法在 word 中登录 Grammarly

目录 1. 情况描述 2. 解决方法 3. 原因分析 1. 情况描述 在浏览器中可以登录 Grammarly&#xff0c;但是在 word 中登录失败&#xff0c;大致如下图所示&#xff1a; 我自己没有截图&#xff0c;这是网上别人的图&#xff0c;但差不多都长这个样子。 2. 解决方法 我点击了…

推荐一个好用的人脑解剖结构及功能注释3D图谱——3D Brain

大脑是一个非凡的结构&#xff0c;它定义了我们是谁&#xff0c;以及我们如何体验世界。神经成像技术的最新进展使我们能够看到大脑内部&#xff0c;让我们能够看到构成大脑的组成部分并了解它们对应的功能。大脑的大体结构对大多数人来说都很熟悉。 前脑的外层构成了我们熟悉…

shell - 正则表达式和grep命令和sed命令

一.正则表达式概述 1.正则表达式定义 1.1 定义 使用字符串描述、匹配一系列符合某个规则的字符串 1.2 了解 普通字符&#xff1a; 大小写字母、数字、标点符号及一些其它符号元字符&#xff1a; 在正则表达式中具有特殊意义的专用字符 1.3 层次分类 基础正则表达式扩展正…

MySQL 备份恢复

1.1 MySQL日志管理 在数据库保存数据时&#xff0c;有时候不可避免会出现数据丢失或者被破坏&#xff0c;这样情况下&#xff0c;我们必须保证数据的安全性和完整性&#xff0c;就需要使用日志来查看或者恢复数据了。 数据库中数据丢失或被破坏可能原因&#xff1a; 误删除数…

机器学习2-简单的二分类问题

需求&#xff1a; 假设现在需要对数据进行二分类&#xff0c;小于0.5的&#xff0c;打上0的标记&#xff0c;大于0.5的&#xff0c;打上1的标记&#xff0c;怎么做&#xff1f; 分析&#xff1a; 这是一个简单的二分类问题&#xff0c;使用逻辑回归模型。 代码&#xff1a; …

【PostgresSQL系列】 ltree简介及基于SpringBoot实现 ltree数据增删改查

本文将对PostgresSQL中的ltree进行相关概念介绍&#xff0c;并以示例代码讲解ltree数据增删改查功能的实现。 作者&#xff1a;后端小肥肠 目录 1.前言 2. 基础概念 2.1. ltree 2.2. lquery 2.3. ltxtquery 2.4. ltree函数及操作符 2.4.1. ltree函数 2.4.2. ltree操作符…

Python实现TCP和UDP通信

目录 一&#xff1a;TCP 二&#xff1a;UDP 一&#xff1a;TCP 在Python中实现TCP通信可以通过使用内置的socket模块来完成。以下是一个简单的示例&#xff0c;展示了如何使用Python的socket模块创建一个TCP客户端和服务器。 TCP服务器 import socket def start_server(): s…

Linux之系统安全与应用续章

目录 一. PAM认证 1.2 初识PAM 1.2.1 PAM及其作用 1.2.2 PAM认证原理 1.2.3 PAM认证的构成 1.2.4 PAM 认证类型 1.2.5 PAM 控制类型 二. limit 三. GRUB加密 /etc/grub.d目录 四. 暴力破解密码 五. 网络扫描--NMAP 六. 总结 一. PAM认证 1.2 初识PAM PAM是Linux系…

【深蓝学院】移动机器人运动规划--第3章 基于采样的路径规划--作业

0. Assignment T1. MATLAB实现RRT 1.1 GPT-4任务分析 RRT伪代码&#xff1a; 任务1即使用matlab实现RRT&#xff0c;结合作业所给框架&#xff0c;简单梳理&#xff0c;可结合1.2代码理解&#xff1a; 设置start&#xff0c;goal&#xff0c;near to goal threshold Thr&am…

react+ts

1.概念 React和TypeScript集合使用的重点集中在 存储数据/状态有关的Hook函数以及组件接口的位置&#xff0c;这些地方最需要数据类型校验 2.使用Vite创建项目 Vite是前端工具链工具&#xff0c;可以帮助我们快速创建一个 reactts 的工程化环境出来 Vite官网&#xff1a;ht…

2024年美赛 (D题ICM)| 湖流网络水位控制 |数学建模完整代码+建模过程全解全析

当大家面临着复杂的数学建模问题时&#xff0c;你是否曾经感到茫然无措&#xff1f;作为2022年美国大学生数学建模比赛的O奖得主&#xff0c;我为大家提供了一套优秀的解题思路&#xff0c;让你轻松应对各种难题。 让我们来看看美赛的D题&#xff01; 完整内容可以在文章末尾领…