【Springboot相关知识】Springboot结合SpringSecurity实现身份认证以及接口鉴权
Springboot结合SpringSecurity实现身份认证以及接口鉴权
- 身份认证
- 1. 添加依赖
- 2. 配置JWT工具类
- 3. 配置Spring Security
- 4. 创建JWT请求过滤器
- 5. 创建认证控制器
- 6. 创建请求和响应对象
- 7. 配置UserDetailsService
- 8. 运行应用程序
- 9. 测试
- 总结
- 接口鉴权
- 1. 启用方法级安全注解
- 2. 定义角色和权限
- 示例:定义用户角色
- 3. 使用注解进行接口鉴权
- 1. `@PreAuthorize`
- 2. `@PostAuthorize`
- 3. `@Secured`
- 4. `@RolesAllowed`
- 4. 配置全局异常处理
- 5. 测试接口鉴权
- 1. 登录获取Token
- 2. 访问受保护的接口
- 6. 总结
- 相关文献
身份认证
在Spring Boot中,使用Spring Security和JWT(JSON Web Token)实现身份认证和接口鉴权是一个常见的需求。下面是一个完整的示例,展示了如何实现这些功能,并支持Token刷新。
1. 添加依赖
首先,在pom.xml中添加必要的依赖:
<dependencies><!-- Spring Boot Starter Web --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><!-- Spring Boot Starter Security --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-security</artifactId></dependency><!-- JWT Library --><dependency><groupId>io.jsonwebtoken</groupId><artifactId>jjwt</artifactId><version>0.9.1</version></dependency><!-- Spring Boot Starter Data JPA (Optional, for UserDetailsService) --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-jpa</artifactId></dependency><!-- H2 Database (Optional, for testing) --><dependency><groupId>com.h2database</groupId><artifactId>h2</artifactId><scope>runtime</scope></dependency>
</dependencies>
2. 配置JWT工具类
创建一个JWT工具类,用于生成和解析JWT Token。
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.stereotype.Component;import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.function.Function;@Component
public class JwtUtil {private String SECRET_KEY = "secret";// 生成Tokenpublic String generateToken(UserDetails userDetails) {Map<String, Object> claims = new HashMap<>();return createToken(claims, userDetails.getUsername());}// 创建Tokenprivate String createToken(Map<String, Object> claims, String subject) {return Jwts.builder().setClaims(claims).setSubject(subject).setIssuedAt(new Date(System.currentTimeMillis())).setExpiration(new Date(System.currentTimeMillis() + 1000 * 60 * 60 * 10)) // 10小时有效期.signWith(SignatureAlgorithm.HS256, SECRET_KEY).compact();}// 验证Tokenpublic Boolean validateToken(String token, UserDetails userDetails) {final String username = extractUsername(token);return (username.equals(userDetails.getUsername()) && !isTokenExpired(token));}// 提取用户名public String extractUsername(String token) {return extractClaim(token, Claims::getSubject);}// 提取过期时间public Date extractExpiration(String token) {return extractClaim(token, Claims::getExpiration);}// 提取Claimpublic <T> T extractClaim(String token, Function<Claims, T> claimsResolver) {final Claims claims = extractAllClaims(token);return claimsResolver.apply(claims);}// 提取所有Claimprivate Claims extractAllClaims(String token) {return Jwts.parser().setSigningKey(SECRET_KEY).parseClaimsJws(token).getBody();}// 判断Token是否过期private Boolean isTokenExpired(String token) {return extractExpiration(token).before(new Date());}
}
3. 配置Spring Security
创建一个Spring Security配置类,配置身份认证和接口鉴权。
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
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.password.NoOpPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {@Autowiredprivate UserDetailsService userDetailsService;@Autowiredprivate JwtRequestFilter jwtRequestFilter;@Overrideprotected void configure(AuthenticationManagerBuilder auth) throws Exception {auth.userDetailsService(userDetailsService);}@Overrideprotected void configure(HttpSecurity http) throws Exception {http.csrf().disable().authorizeRequests().antMatchers("/authenticate", "/refreshToken").permitAll() // 允许匿名访问的接口.anyRequest().authenticated() // 其他接口需要认证.and().sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS); // 无状态会话http.addFilterBefore(jwtRequestFilter, UsernamePasswordAuthenticationFilter.class);}@Beanpublic PasswordEncoder passwordEncoder() {return NoOpPasswordEncoder.getInstance(); // 仅用于示例,生产环境应使用BCryptPasswordEncoder}@Override@Beanpublic AuthenticationManager authenticationManagerBean() throws Exception {return super.authenticationManagerBean();}
}
4. 创建JWT请求过滤器
创建一个过滤器,用于在每次请求中验证JWT Token。
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.web.authentication.WebAuthenticationDetailsSource;
import org.springframework.stereotype.Component;
import org.springframework.web.filter.OncePerRequestFilter;import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;@Component
public class JwtRequestFilter extends OncePerRequestFilter {@Autowiredprivate UserDetailsService userDetailsService;@Autowiredprivate JwtUtil jwtUtil;@Overrideprotected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain)throws ServletException, IOException {final String authorizationHeader = request.getHeader("Authorization");String username = null;String jwt = null;if (authorizationHeader != null && authorizationHeader.startsWith("Bearer ")) {jwt = authorizationHeader.substring(7);username = jwtUtil.extractUsername(jwt);}if (username != null && SecurityContextHolder.getContext().getAuthentication() == null) {UserDetails userDetails = this.userDetailsService.loadUserByUsername(username);if (jwtUtil.validateToken(jwt, userDetails)) {UsernamePasswordAuthenticationToken usernamePasswordAuthenticationToken = new UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities());usernamePasswordAuthenticationToken.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));SecurityContextHolder.getContext().setAuthentication(usernamePasswordAuthenticationToken);}}chain.doFilter(request, response);}
}
5. 创建认证控制器
创建一个控制器,用于处理用户登录和Token刷新。
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.web.bind.annotation.*;@RestController
public class AuthenticationController {@Autowiredprivate AuthenticationManager authenticationManager;@Autowiredprivate UserDetailsService userDetailsService;@Autowiredprivate JwtUtil jwtUtil;@PostMapping("/authenticate")public ResponseEntity<?> createAuthenticationToken(@RequestBody AuthenticationRequest authenticationRequest) throws Exception {try {authenticationManager.authenticate(new UsernamePasswordAuthenticationToken(authenticationRequest.getUsername(), authenticationRequest.getPassword()));} catch (Exception e) {throw new Exception("Incorrect username or password", e);}final UserDetails userDetails = userDetailsService.loadUserByUsername(authenticationRequest.getUsername());final String jwt = jwtUtil.generateToken(userDetails);return ResponseEntity.ok(new AuthenticationResponse(jwt));}@PostMapping("/refreshToken")public ResponseEntity<?> refreshAuthenticationToken(@RequestHeader("Authorization") String oldToken) {String username = jwtUtil.extractUsername(oldToken.substring(7));UserDetails userDetails = userDetailsService.loadUserByUsername(username);if (jwtUtil.validateToken(oldToken.substring(7), userDetails)) {String newToken = jwtUtil.generateToken(userDetails);return ResponseEntity.ok(new AuthenticationResponse(newToken));}return ResponseEntity.badRequest().body("Invalid token");}
}
6. 创建请求和响应对象
创建用于封装请求和响应的对象。
public class AuthenticationRequest {private String username;private String password;// Getters and Setters
}public class AuthenticationResponse {private final String jwt;public AuthenticationResponse(String jwt) {this.jwt = jwt;}public String getJwt() {return jwt;}
}
7. 配置UserDetailsService
实现UserDetailsService接口,用于加载用户信息。
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.stereotype.Service;import java.util.ArrayList;@Service
public class MyUserDetailsService implements UserDetailsService {@Overridepublic UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {// 这里可以从数据库中加载用户信息return new User("user", "password", new ArrayList<>());}
}
8. 运行应用程序
现在,你可以运行Spring Boot应用程序,并通过以下接口进行测试:
- 登录接口:
POST /authenticate - 刷新Token接口:
POST /refreshToken - 受保护的接口: 任何其他接口都需要在请求头中添加
Authorization: Bearer <token>。
9. 测试
你可以使用Postman或curl等工具进行测试:
-
登录请求:
POST /authenticate {"username": "user","password": "password" } -
刷新Token请求:
POST /refreshToken Authorization: Bearer <old_token>
总结
通过以上步骤,我们实现了一个基于Spring Security和JWT的身份认证和接口鉴权系统,并支持Token刷新。你可以根据实际需求进一步扩展和优化这个系统。
接口鉴权
在Spring Security中,接口鉴权通常通过配置HttpSecurity来实现。我们可以使用注解(如@PreAuthorize、@PostAuthorize、@Secured等)来细粒度地控制接口的访问权限。以下是接口鉴权的详细实现和示例。
1. 启用方法级安全注解
在Spring Boot中,默认情况下方法级安全注解是关闭的。我们需要在配置类中启用它。
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.method.configuration.GlobalMethodSecurityConfiguration;@Configuration
@EnableGlobalMethodSecurity(prePostEnabled = true, // 启用@PreAuthorize和@PostAuthorize注解securedEnabled = true, // 启用@Secured注解jsr250Enabled = true // 启用@RolesAllowed注解
)
public class MethodSecurityConfig extends GlobalMethodSecurityConfiguration {
}
2. 定义角色和权限
在Spring Security中,角色和权限通常通过UserDetails实现类来定义。我们可以为用户分配角色或权限,然后在接口上使用注解进行鉴权。
示例:定义用户角色
在UserDetailsService中,为用户分配角色:
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.stereotype.Service;import java.util.Arrays;@Service
public class MyUserDetailsService implements UserDetailsService {@Overridepublic UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {if ("admin".equals(username)) {return new User("admin", "password", Arrays.asList(new SimpleGrantedAuthority("ROLE_ADMIN")));} else if ("user".equals(username)) {return new User("user", "password", Arrays.asList(new SimpleGrantedAuthority("ROLE_USER")));} else {throw new UsernameNotFoundException("User not found with username: " + username);}}
}
3. 使用注解进行接口鉴权
Spring Security提供了多种注解来实现接口鉴权。以下是常用的注解及其用法:
1. @PreAuthorize
在方法执行前进行权限检查。
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;@RestController
@RequestMapping("/api")
public class ApiController {// 只有ADMIN角色可以访问@GetMapping("/admin")@PreAuthorize("hasRole('ADMIN')")public String adminEndpoint() {return "Hello Admin!";}// 只有USER角色可以访问@GetMapping("/user")@PreAuthorize("hasRole('USER')")public String userEndpoint() {return "Hello User!";}// 同时支持ADMIN和USER角色@GetMapping("/all")@PreAuthorize("hasAnyRole('ADMIN', 'USER')")public String allEndpoint() {return "Hello All!";}// 自定义权限表达式@GetMapping("/custom")@PreAuthorize("hasAuthority('READ_PRIVILEGE')")public String customEndpoint() {return "Custom Access!";}
}
2. @PostAuthorize
在方法执行后进行权限检查。
import org.springframework.security.access.prepost.PostAuthorize;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;@RestController
@RequestMapping("/api")
public class ApiController {// 方法执行后检查返回值@GetMapping("/postAuth")@PostAuthorize("returnObject == 'Hello Admin!'")public String postAuthEndpoint() {return "Hello Admin!";}
}
3. @Secured
基于角色的简单鉴权。
import org.springframework.security.access.annotation.Secured;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;@RestController
@RequestMapping("/api")
public class ApiController {// 只有ADMIN角色可以访问@GetMapping("/secured")@Secured("ROLE_ADMIN")public String securedEndpoint() {return "Secured Access!";}
}
4. @RolesAllowed
基于JSR-250标准的角色鉴权。
import javax.annotation.security.RolesAllowed;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;@RestController
@RequestMapping("/api")
public class ApiController {// 只有ADMIN角色可以访问@GetMapping("/rolesAllowed")@RolesAllowed("ADMIN")public String rolesAllowedEndpoint() {return "Roles Allowed Access!";}
}
4. 配置全局异常处理
当用户访问未授权的接口时,Spring Security会抛出AccessDeniedException。我们可以通过全局异常处理来返回友好的错误信息。
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;@RestControllerAdvice
public class GlobalExceptionHandler {// 处理权限不足异常@ExceptionHandler(AccessDeniedException.class)public ResponseEntity<String> handleAccessDeniedException(AccessDeniedException e) {return ResponseEntity.status(HttpStatus.FORBIDDEN).body("Access Denied: " + e.getMessage());}// 处理其他异常@ExceptionHandler(Exception.class)public ResponseEntity<String> handleException(Exception e) {return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body("Error: " + e.getMessage());}
}
5. 测试接口鉴权
使用Postman或curl测试接口:
1. 登录获取Token
POST /authenticate
{"username": "admin","password": "password"
}
2. 访问受保护的接口
-
ADMIN接口:
GET /api/admin Authorization: Bearer <token> -
USER接口:
GET /api/user Authorization: Bearer <token> -
未授权访问:
如果用户没有权限,会返回403 Forbidden。
6. 总结
通过以上步骤,我们实现了基于Spring Security的接口鉴权功能。主要步骤包括:
- 启用方法级安全注解。
- 定义用户角色和权限。
- 使用注解(如
@PreAuthorize、@Secured等)控制接口访问权限。 - 配置全局异常处理,返回友好的错误信息。
你可以根据实际需求扩展和调整这些配置,例如从数据库中动态加载权限、支持更复杂的权限表达式等。
相关文献
JWT(JSON Web Tokens) 详细介绍
【spring知识】Spring Security从入门到放弃
相关文章:
【Springboot相关知识】Springboot结合SpringSecurity实现身份认证以及接口鉴权
Springboot结合SpringSecurity实现身份认证以及接口鉴权 身份认证1. 添加依赖2. 配置JWT工具类3. 配置Spring Security4. 创建JWT请求过滤器5. 创建认证控制器6. 创建请求和响应对象7. 配置UserDetailsService8. 运行应用程序9. 测试总结 接口鉴权1. 启用方法级安全注解2. 定义…...
算法竞赛之差分进阶——等差数列差分 python
目录 前置知识进入正题实战演练 前置知识 给定区间 [ l, r ],让我们把数组中的[ l, r ] 区间中的每一个数加上c,即 a[ l ] c , a[ l 1 ] c , a[ l 2] c , a[ r ] c; 怎么做?很简单,差分一下即可 还不会的小伙伴点此进入学习 进入正题 …...
20250121在Ubuntu20.04.6下使用Linux_Upgrade_Tool工具给荣品的PRO-RK3566开发板刷机
sudo upgrade_tool uf update.img 20250121在Ubuntu20.04.6下使用Linux_Upgrade_Tool工具给荣品的PRO-RK3566开发板刷机 2025/1/21 11:54 百度:ubuntu RK3566 刷机 firefly rk3566 ubuntu upgrade_tool烧写详解 https://wiki.t-firefly.com/Core-3566JD4/03-upgrad…...
【Elasticsearch】Springboot编写Elasticsearch的RestAPI
RestAPI 初始化RestClient创建索引库Mapping映射 判断索引库是否存在删除索引库总结 ES官方提供了各种不同语言的客户端,用来操作ES。这些客户端的本质就是组装DSL语句,通过http请求发送给ES。 官方文档地址 由于ES目前最新版本是8.8,提供了全…...
Python数据可视化(够用版):懂基础 + 专业的图表抛给Tableau等专业绘图工具
我先说说文章标题中的“够用版”啥意思,为什么这么写。 按照我个人观点,在使用Python进行数据分析时,我们有时候肯定要结合到图表去进行分析,去直观展现数据的规律和特定,那么我们肯定要做一些简单的可视化࿰…...
1.21学习
misc buuctf-爱因斯坦 下载附件后是一个图片,用stegsolve查看一下,各个色都没有问题,然后看一下数据分析,除此之外无其他信息,再看看图片属性,不知道是啥,用随波逐流进行binwalk文件提取然后得…...
SoftGNSS软件接收机源码阅读(一)程序简介、运行调试、执行流程
原始 Markdown文档、Visio流程图、XMind思维导图见:https://github.com/LiZhengXiao99/Navigation-Learning 文章目录 一、softGNSS 简介1、概述2、相关工作3、我用 softGNSS 做的事4、文件结构5、程序执行流程图 二、程序使用1、射频前端2、参数设置3、处理开源数据…...
Spring Boot AOP实现动态数据脱敏
依赖&配置 <!-- Spring Boot AOP起步依赖 --> <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-aop</artifactId> </dependency>/*** Author: 说淑人* Date: 2025/1/18 23:03* Desc…...
Leetcode刷题-二分查找
灵神的二分视频:二分查找 红蓝染色法_哔哩哔哩_bilibili 34 class Solution:def searchRange(self, nums: List[int], target: int) -> List[int]:right len(nums) - 1left 0res [-1,-1]mid int((right left)/2)while right > left:if nums[mid] < …...
凭证Account Assignment的校验(FAGL_VALIDATE)
本文主要介绍在S4 HANA OP中凭证Account Assignment的校验配置。具体请参照如下内容: 目录 1. 定义Account Assignment校验策略(FAGL_VALIDATE) 1.1 Derivation Rule 1.2 Assignment 1.3 Initialize 1.4 Enhancement 2. 分配Account Assignment校验策略给公司…...
【20】Word:小许-质量管理-论文❗
目录 题目 NO1.2.3.4.5 NO6.7 NO8 NO9 NO10.11 题目 NO1.2.3.4.5 另存为“Word.docx”文件在考生文件夹下,F12Fn是另存为的作用布局→页面设置对话框→纸张:大小A4→页边距:上下左右不连续ctrl选择除表格外的所有内容→开始→字体对…...
二十八、Qos服务质量
Qos服务质量 一、产生原因 Resources也不是万能的,使用一段时间后,资源总量可能会超过接节点配置。 根据这个情况,我们可以设置,清除资源。给pod配置,按顺序删除 二、服务质量QoS分类 Guaranteed:最高服务质量(保证),当宿主机内存不够时,会先kill掉QoS为BestEffort…...
Flutter 改完安卓 applicationId 后App 闪退问题。
一、问题 当我们项目创建完,想 build.gradle 改 applicationId 的时候,再次执行的时候可能会出现 app 闪退问题, 控制台不显示任何错误提示 也不出现 Exit 停止运行的情况。(像下方这样, 而 app 只是在模拟器中一闪而…...
es 3期 第25节-运用Rollup减少数据存储
#### 1.Elasticsearch是数据库,不是普通的Java应用程序,传统数据库需要的硬件资源同样需要,提升性能最有效的就是升级硬件。 #### 2.Elasticsearch是文档型数据库,不是关系型数据库,不具备严格的ACID事务特性ÿ…...
小菜鸟系统学习Python第三天
1.优先级问题: 结论: 幂运算>正负号>加减乘除和整除>比较运算符>逻辑运算符 2.三元运算符 3.assert断言:抛出AssertionError异常 4.for循环 4. 5.break和continue...
七.网络模型
最小(支撑)树问题 最小部分树求解: 破圈法:任取一圈,去掉圈中最长边,直到无圈; 加边法:取图G的n个孤立点{v1,v2,…, vn }作为一个支撑图,从最短…...
1170 Safari Park (25)
A safari park(野生动物园)has K species of animals, and is divided into N regions. The managers hope to spread the animals to all the regions, but not the same animals in the two neighboring regions. Of course, they also realize that t…...
数字图像处理:实验五
uu们!大家好,欢迎来到数字图像处理第五章节内容的学习,在本章中有关空间滤波的理论学习是十分重要的,所以建议大家要去用心的学习本章,在之后的传感器的相关图像采集时,不可避免的会有噪声等的影响…...
2024我在csdn走过的路
自我介绍 ✏️博客名✏️: zy_destiny 🌸粉丝数🌸: 1万 🌿擅长领域🌿: 人工智能 👀欢迎访问👀: 我的主页 我的2024 回顾下2024年,起点要从去年写…...
网络安全等级保护基本要求——等保二级
《信息安全技术网络安全等级保护基本要求》GB/T22239-2019 7.1 安全通用要求 7.1.1 安全物理环境 7.1.1.1 物理位置选择 本项要求包括: a) 机房场地应选择在具有防震、防风和防雨等能力的建筑内;b) 机房场地应避免设在建筑物的顶层或地下室,否则应加…...
业务系统对接大模型的基础方案:架构设计与关键步骤
业务系统对接大模型:架构设计与关键步骤 在当今数字化转型的浪潮中,大语言模型(LLM)已成为企业提升业务效率和创新能力的关键技术之一。将大模型集成到业务系统中,不仅可以优化用户体验,还能为业务决策提供…...
XCTF-web-easyupload
试了试php,php7,pht,phtml等,都没有用 尝试.user.ini 抓包修改将.user.ini修改为jpg图片 在上传一个123.jpg 用蚁剑连接,得到flag...
【git】把本地更改提交远程新分支feature_g
创建并切换新分支 git checkout -b feature_g 添加并提交更改 git add . git commit -m “实现图片上传功能” 推送到远程 git push -u origin feature_g...
NFT模式:数字资产确权与链游经济系统构建
NFT模式:数字资产确权与链游经济系统构建 ——从技术架构到可持续生态的范式革命 一、确权技术革新:构建可信数字资产基石 1. 区块链底层架构的进化 跨链互操作协议:基于LayerZero协议实现以太坊、Solana等公链资产互通,通过零知…...
实现弹窗随键盘上移居中
实现弹窗随键盘上移的核心思路 在Android中,可以通过监听键盘的显示和隐藏事件,动态调整弹窗的位置。关键点在于获取键盘高度,并计算剩余屏幕空间以重新定位弹窗。 // 在Activity或Fragment中设置键盘监听 val rootView findViewById<V…...
USB Over IP专用硬件的5个特点
USB over IP技术通过将USB协议数据封装在标准TCP/IP网络数据包中,从根本上改变了USB连接。这允许客户端通过局域网或广域网远程访问和控制物理连接到服务器的USB设备(如专用硬件设备),从而消除了直接物理连接的需要。USB over IP的…...
Reasoning over Uncertain Text by Generative Large Language Models
https://ojs.aaai.org/index.php/AAAI/article/view/34674/36829https://ojs.aaai.org/index.php/AAAI/article/view/34674/36829 1. 概述 文本中的不确定性在许多语境中传达,从日常对话到特定领域的文档(例如医学文档)(Heritage 2013;Landmark、Gulbrandsen 和 Svenevei…...
九天毕昇深度学习平台 | 如何安装库?
pip install 库名 -i https://pypi.tuna.tsinghua.edu.cn/simple --user 举个例子: 报错 ModuleNotFoundError: No module named torch 那么我需要安装 torch pip install torch -i https://pypi.tuna.tsinghua.edu.cn/simple --user pip install 库名&#x…...
LeetCode - 199. 二叉树的右视图
题目 199. 二叉树的右视图 - 力扣(LeetCode) 思路 右视图是指从树的右侧看,对于每一层,只能看到该层最右边的节点。实现思路是: 使用深度优先搜索(DFS)按照"根-右-左"的顺序遍历树记录每个节点的深度对于…...
短视频矩阵系统文案创作功能开发实践,定制化开发
在短视频行业迅猛发展的当下,企业和个人创作者为了扩大影响力、提升传播效果,纷纷采用短视频矩阵运营策略,同时管理多个平台、多个账号的内容发布。然而,频繁的文案创作需求让运营者疲于应对,如何高效产出高质量文案成…...
