当前位置: 首页 > news >正文

认证授权系统设计

以下是一个完整的认证授权系统的Java实现,包含常见的认证授权功能如JWT生成与验证、角色权限控制等。

1. 项目结构

src/
├── main/
│   ├── java/
│   │   └── com/
│   │       └── example/
│   │           └── auth/
│   │               ├── config/          # 配置类
│   │               ├── controller/      # 控制器
│   │               ├── dto/             # 数据传输对象
│   │               ├── entity/          # 实体类
│   │               ├── exception/       # 异常处理
│   │               ├── repository/      # 数据访问
│   │               ├── security/        # 安全相关
│   │               ├── service/         # 业务逻辑
│   │               └── AuthApplication.java
│   └── resources/
│       └── application.yml             # 配置文件
└── test/                               # 测试代码

2. 完整代码实现

2.1 主应用类

package com.example.auth;import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;@SpringBootApplication
@EnableGlobalMethodSecurity(prePostEnabled = true) // 启用方法级别的权限控制
public class AuthApplication {public static void main(String[] args) {SpringApplication.run(AuthApplication.class, args);}
}

2.2 配置类

WebSecurityConfig.java
package com.example.auth.config;import com.example.auth.security.JwtAuthenticationEntryPoint;
import com.example.auth.security.JwtAuthenticationFilter;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
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.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;@Configuration
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {private final UserDetailsService userDetailsService;private final JwtAuthenticationEntryPoint unauthorizedHandler;public WebSecurityConfig(UserDetailsService userDetailsService, JwtAuthenticationEntryPoint unauthorizedHandler) {this.userDetailsService = userDetailsService;this.unauthorizedHandler = unauthorizedHandler;}@Beanpublic JwtAuthenticationFilter jwtAuthenticationFilter() {return new JwtAuthenticationFilter();}@Beanpublic PasswordEncoder passwordEncoder() {return new BCryptPasswordEncoder();}@Overridepublic void configure(AuthenticationManagerBuilder auth) throws Exception {auth.userDetailsService(userDetailsService).passwordEncoder(passwordEncoder());}@Bean@Overridepublic AuthenticationManager authenticationManagerBean() throws Exception {return super.authenticationManagerBean();}@Overrideprotected void configure(HttpSecurity http) throws Exception {http.cors().and().csrf().disable().exceptionHandling().authenticationEntryPoint(unauthorizedHandler).and().sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS).and().authorizeRequests().antMatchers("/api/auth/**").permitAll().antMatchers("/api/test/**").permitAll().anyRequest().authenticated();http.addFilterBefore(jwtAuthenticationFilter(), UsernamePasswordAuthenticationFilter.class);}
}
JwtConfig.java
package com.example.auth.config;import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;@Component
public class JwtConfig {@Value("${jwt.secret}")private String secret;@Value("${jwt.expiration}")private Long expiration;@Value("${jwt.tokenPrefix}")private String tokenPrefix;@Value("${jwt.headerString}")private String headerString;// Getterspublic String getSecret() {return secret;}public Long getExpiration() {return expiration;}public String getTokenPrefix() {return tokenPrefix;}public String getHeaderString() {return headerString;}
}

2.3 实体类

User.java
package com.example.auth.entity;import javax.persistence.*;
import java.util.HashSet;
import java.util.Set;@Entity
@Table(name = "users")
public class User {@Id@GeneratedValue(strategy = GenerationType.IDENTITY)private Long id;@Column(nullable = false, unique = true)private String username;@Column(nullable = false)private String password;@ManyToMany(fetch = FetchType.LAZY)@JoinTable(name = "user_roles",joinColumns = @JoinColumn(name = "user_id"),inverseJoinColumns = @JoinColumn(name = "role_id"))private Set<Role> roles = new HashSet<>();// Constructors, getters and setterspublic User() {}public User(String username, String password) {this.username = username;this.password = password;}// Getters and setterspublic Long getId() {return id;}public void setId(Long id) {this.id = id;}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 Set<Role> getRoles() {return roles;}public void setRoles(Set<Role> roles) {this.roles = roles;}
}
Role.java
package com.example.auth.entity;import javax.persistence.*;
import java.util.HashSet;
import java.util.Set;@Entity
@Table(name = "roles")
public class Role {@Id@GeneratedValue(strategy = GenerationType.IDENTITY)private Long id;@Enumerated(EnumType.STRING)@Column(length = 20)private ERole name;@ManyToMany(mappedBy = "roles")private Set<User> users = new HashSet<>();public Role() {}public Role(ERole name) {this.name = name;}// Getters and setterspublic Long getId() {return id;}public void setId(Long id) {this.id = id;}public ERole getName() {return name;}public void setName(ERole name) {this.name = name;}public Set<User> getUsers() {return users;}public void setUsers(Set<User> users) {this.users = users;}
}
ERole.java
package com.example.auth.entity;public enum ERole {ROLE_USER,ROLE_MODERATOR,ROLE_ADMIN
}

2.4 DTO类

LoginRequest.java
package com.example.auth.dto;import javax.validation.constraints.NotBlank;public class LoginRequest {@NotBlankprivate String username;@NotBlankprivate String password;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;}
}
SignupRequest.java
package com.example.auth.dto;import javax.validation.constraints.*;
import java.util.Set;public class SignupRequest {@NotBlank@Size(min = 3, max = 20)private String username;@NotBlank@Size(max = 50)@Emailprivate String email;private Set<String> roles;@NotBlank@Size(min = 6, max = 40)private String password;// Getters and setterspublic String getUsername() {return username;}public void setUsername(String username) {this.username = username;}public String getEmail() {return email;}public void setEmail(String email) {this.email = email;}public String getPassword() {return password;}public void setPassword(String password) {this.password = password;}public Set<String> getRoles() {return roles;}public void setRoles(Set<String> roles) {this.roles = roles;}
}
JwtResponse.java
package com.example.auth.dto;import java.util.List;public class JwtResponse {private String token;private String type = "Bearer";private Long id;private String username;private List<String> roles;public JwtResponse(String accessToken, Long id, String username, List<String> roles) {this.token = accessToken;this.id = id;this.username = username;this.roles = roles;}// Getterspublic String getAccessToken() {return token;}public String getTokenType() {return type;}public Long getId() {return id;}public String getUsername() {return username;}public List<String> getRoles() {return roles;}
}

2.5 异常处理

AppException.java
package com.example.auth.exception;import org.springframework.http.HttpStatus;public class AppException extends RuntimeException {private final HttpStatus status;public AppException(String message, HttpStatus status) {super(message);this.status = status;}public HttpStatus getStatus() {return status;}
}
GlobalExceptionHandler.java
package com.example.auth.exception;import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.context.request.WebRequest;import java.util.Date;@RestControllerAdvice
public class GlobalExceptionHandler {@ExceptionHandler(AppException.class)public ResponseEntity<ErrorMessage> handleAppException(AppException ex, WebRequest request) {ErrorMessage message = new ErrorMessage(new Date(),ex.getMessage(),request.getDescription(false),ex.getStatus().value());return new ResponseEntity<>(message, ex.getStatus());}@ExceptionHandler(Exception.class)public ResponseEntity<ErrorMessage> handleGlobalException(Exception ex, WebRequest request) {ErrorMessage message = new ErrorMessage(new Date(),ex.getMessage(),request.getDescription(false),500);return new ResponseEntity<>(message, HttpStatus.INTERNAL_SERVER_ERROR);}
}

2.6 安全相关

JwtAuthenticationEntryPoint.java
package com.example.auth.security;import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.AuthenticationEntryPoint;
import org.springframework.stereotype.Component;import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;@Component
public class JwtAuthenticationEntryPoint implements AuthenticationEntryPoint {@Overridepublic void commence(HttpServletRequest request, HttpServletResponse response,AuthenticationException authException) throws IOException {response.sendError(HttpServletResponse.SC_UNAUTHORIZED, "Unauthorized");}
}
JwtAuthenticationFilter.java
package com.example.auth.security;import com.example.auth.config.JwtConfig;
import com.example.auth.service.UserDetailsServiceImpl;
import io.jsonwebtoken.ExpiredJwtException;
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 JwtAuthenticationFilter extends OncePerRequestFilter {@Autowiredprivate JwtTokenProvider tokenProvider;@Autowiredprivate UserDetailsServiceImpl userDetailsService;@Autowiredprivate JwtConfig jwtConfig;@Overrideprotected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)throws ServletException, IOException {try {String jwt = getJwtFromRequest(request);if (jwt != && tokenProvider.validateToken(jwt)) {Long userId = tokenProvider.getUserIdFromToken(jwt);UserDetails userDetails = userDetailsService.loadUserById(userId);UsernamePasswordAuthenticationToken authentication =new UsernamePasswordAuthenticationToken(userDetails,, userDetails.getAuthorities());authentication.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));SecurityContextHolder.getContext().setAuthentication(authentication);}} catch (ExpiredJwtException ex) {request.setAttribute("exception", ex);} catch (Exception ex) {logger.error("Could not set user authentication in security context", ex);}filterChain.doFilter(request, response);}private String getJwtFromRequest(HttpServletRequest request) {String bearerToken = request.getHeader(jwtConfig.getHeaderString());if (bearerToken != && bearerToken.startsWith(jwtConfig.getTokenPrefix())) {return bearerToken.substring(jwtConfig.getTokenPrefix().length() + 1);}return;}
}
JwtTokenProvider.java
package com.example.auth.security;import com.example.auth.config.JwtConfig;
import io.jsonwebtoken.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.Authentication;
import org.springframework.stereotype.Component;import java.util.Date;@Component
public class JwtTokenProvider {private static final Logger logger = LoggerFactory.getLogger(JwtTokenProvider.class);@Autowiredprivate JwtConfig jwtConfig;public String generateToken(Authentication authentication) {UserPrincipal userPrincipal = (UserPrincipal) authentication.getPrincipal();Date now = new Date();Date expiryDate = new Date(now.getTime() + jwtConfig.getExpiration());return Jwts.builder().setSubject(userPrincipal.getId().toString()).setIssuedAt(new Date()).setExpiration(expiryDate).signWith(SignatureAlgorithm.HS512, jwtConfig.getSecret()).compact();}public Long getUserIdFromToken(String token) {Claims claims = Jwts.parser().setSigningKey(jwtConfig.getSecret()).parseClaimsJws(token).getBody();return Long.parseLong(claims.getSubject());}public boolean validateToken(String authToken) {try {Jwts.parser().setSigningKey(jwtConfig.getSecret()).parseClaimsJws(authToken);return true;} catch (SignatureException ex) {logger.error("Invalid JWT signature");} catch (MalformedJwtException ex) {logger.error("Invalid JWT token");} catch (ExpiredJwtException ex) {logger.error("Expired JWT token");} catch (UnsupportedJwtException ex) {logger.error("Unsupported JWT token");} catch (IllegalArgumentException ex) {logger.error("JWT claims string is empty");}return false;}
}
UserPrincipal.java
package com.example.auth.security;import com.example.auth.entity.User;
import com.fasterxml.jackson.annotation.JsonIgnore;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;import java.util.Collection;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;public class UserPrincipal implements UserDetails {private Long id;private String username;@JsonIgnoreprivate String password;private Collection<? extends GrantedAuthority> authorities;public UserPrincipal(Long id, String username, String password,Collection<? extends GrantedAuthority> authorities) {this.id = id;this.username = username;this.password = password;this.authorities = authorities;}public static UserPrincipal create(User user) {List<GrantedAuthority> authorities = user.getRoles().stream().map(role -> new SimpleGrantedAuthority(role.getName().name())).collect(Collectors.toList());return new UserPrincipal(user.getId(),user.getUsername(),user.getPassword(),authorities);}public Long getId() {return id;}@Overridepublic String getUsername() {return username;}@Overridepublic String getPassword() {return password;}@Overridepublic Collection<? extends GrantedAuthority> getAuthorities() {return authorities;}@Overridepublic boolean isAccountNonExpired() {return true;}@Overridepublic boolean isAccountNonLocked() {return true;}@Overridepublic boolean isCredentialsNonExpired() {return true;}@Overridepublic boolean isEnabled() {return true;}@Overridepublic boolean equals(Object o) {if (this == o) return true;if (o == || getClass() != o.getClass()) return false;UserPrincipal that = (UserPrincipal) o;return Objects.equals(id, that.id);}@Overridepublic int hashCode() {return Objects.hash(id);}
}

2.7 服务层

AuthService.java
package com.example.auth.service;import com.example.auth.dto.LoginRequest;
import com.example.auth.dto.SignupRequest;
import com.example.auth.dto.JwtResponse;
import com.example.auth.entity.ERole;
import com.example.auth.entity.Role;
import com.example.auth.entity.User;
import com.example.auth.exception.AppException;
import com.example.auth.repository.RoleRepository;
import com.example.auth.repository.UserRepository;
import com.example.auth.security.JwtTokenProvider;
import com.example.auth.security.UserPrincipal;
import org.springframework.http.HttpStatus;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;@Service
public class AuthService {private final AuthenticationManager authenticationManager;private final UserRepository userRepository;private final RoleRepository roleRepository;private final PasswordEncoder passwordEncoder;private final JwtTokenProvider tokenProvider;public AuthService(AuthenticationManager authenticationManager,UserRepository userRepository,RoleRepository roleRepository,PasswordEncoder passwordEncoder,JwtTokenProvider tokenProvider) {this.authenticationManager = authenticationManager;this.userRepository = userRepository;this.roleRepository = roleRepository;this.passwordEncoder = passwordEncoder;this.tokenProvider = tokenProvider;}public JwtResponse authenticateUser(LoginRequest loginRequest) {Authentication authentication = authenticationManager.authenticate(new UsernamePasswordAuthenticationToken(loginRequest.getUsername(),loginRequest.getPassword()));SecurityContextHolder.getContext().setAuthentication(authentication);String jwt = tokenProvider.generateToken(authentication);UserPrincipal userPrincipal = (UserPrincipal) authentication.getPrincipal();List<String> roles = userPrincipal.getAuthorities().stream().map(GrantedAuthority -> GrantedAuthority.getAuthority()).collect(Collectors.toList());return new JwtResponse(jwt, userPrincipal.getId(), userPrincipal.getUsername(), roles);}public User registerUser(SignupRequest signUpRequest) {if (userRepository.existsByUsername(signUpRequest.getUsername())) {throw new AppException("Username is already taken!", HttpStatus.BAD_REQUEST);}// Creating user's accountUser user = new User(signUpRequest.getUsername(),passwordEncoder.encode(signUpRequest.getPassword()));Set<String> strRoles = signUpRequest.getRoles();Set<Role> roles = new HashSet<>();if (strRoles ==) {Role userRole = roleRepository.findByName(ERole.ROLE_USER).orElseThrow(() -> new AppException("Role is not found.", HttpStatus.INTERNAL_SERVER_ERROR));roles.add(userRole);} else {strRoles.forEach(role -> {switch (role) {case "admin":Role adminRole = roleRepository.findByName(ERole.ROLE_ADMIN).orElseThrow(() -> new AppException("Role is not found.", HttpStatus.INTERNAL_SERVER_ERROR));roles.add(adminRole);break;case "mod":Role modRole = roleRepository.findByName(ERole.ROLE_MODERATOR).orElseThrow(() -> new AppException("Role is not found.", HttpStatus.INTERNAL_SERVER_ERROR));roles.add(modRole);break;default:Role userRole = roleRepository.findByName(ERole.ROLE_USER).orElseThrow(() -> new AppException("Role is not found.", HttpStatus.INTERNAL_SERVER_ERROR));roles.add(userRole);}});}user.setRoles(roles);return userRepository.save(user);}
}
UserDetailsServiceImpl.java
package com.example.auth.service;import com.example.auth.entity.User;
import com.example.auth.repository.UserRepository;
import com.example.auth.security.UserPrincipal;
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.transaction.annotation.Transactional;@Service
public class UserDetailsServiceImpl implements UserDetailsService {private final UserRepository userRepository;public UserDetailsServiceImpl(UserRepository userRepository) {this.userRepository = userRepository;}@Override@Transactionalpublic UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {User user = userRepository.findByUsername(username).orElseThrow(() -> new UsernameNotFoundException("User not found with username: " + username));return UserPrincipal.create(user);}@Transactionalpublic UserDetails loadUserById(Long id) {User user = userRepository.findById(id).orElseThrow(() -> new UsernameNotFoundException("User not found with id: " + id));return UserPrincipal.create(user);}
}

2.8 仓库层

UserRepository.java
package com.example.auth.repository;import com.example.auth.entity.User;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;import java.util.Optional;@Repository
public interface UserRepository extends JpaRepository<User, Long> {Optional<User> findByUsername(String username);Boolean existsByUsername(String username);
}
RoleRepository.java
package com.example.auth.repository;import com.example.auth.entity.ERole;
import com.example.auth.entity.Role;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;import java.util.Optional;@Repository
public interface RoleRepository extends JpaRepository<Role, Long> {Optional<Role> findByName(ERole name);
}

2.9 控制器层

AuthController.java
package com.example.auth.controller;import com.example.auth.dto.JwtResponse;
import com.example.auth.dto.LoginRequest;
import com.example.auth.dto.SignupRequest;
import com.example.auth.entity.User;
import com.example.auth.service.AuthService;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;import javax.validation.Valid;@RestController
@RequestMapping("/api/auth")
public class AuthController {private final AuthService authService;public AuthController(AuthService authService) {this.authService = authService;}@PostMapping("/signin")public ResponseEntity<JwtResponse> authenticateUser(@Valid @RequestBody LoginRequest loginRequest) {JwtResponse jwtResponse = authService.authenticateUser(loginRequest);return ResponseEntity.ok(jwtResponse);}@PostMapping("/signup")public ResponseEntity<User> registerUser(@Valid @RequestBody SignupRequest signUpRequest) {User user = authService.registerUser(signUpRequest);return ResponseEntity.ok(user);}
}
TestController.java
package com.example.auth.controller;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/test")
public class TestController {@GetMapping("/all")public String allAccess() {return "Public Content.";}@GetMapping("/user")@PreAuthorize("hasRole('USER') or hasRole('MODERATOR') or hasRole('ADMIN')")public String userAccess() {return "User Content.";}@GetMapping("/mod")@PreAuthorize("hasRole('MODERATOR')")public String moderatorAccess() {return "Moderator Board.";}@GetMapping("/admin")@PreAuthorize("hasRole('ADMIN')")public String adminAccess() {return "Admin Board.";}
}

2.10 配置文件

application.yml
server:port: 8080spring:datasource:url: jdbc:h2:mem:testdbdriver-class-name: org.h2.Driverusername: sapassword:jpa:database-platform: org.hibernate.dialect.H2Dialecthibernate:ddl-auto: create-dropshow-sql: trueh2:console:enabled: truepath: /h2-consolejwt:secret: mySecretexpiration: 86400000 # 24 hourstokenPrefix: BearerheaderString: Authorization

3. 功能说明

这个认证授权系统实现了以下功能:

  1. 用户认证
    • 使用JWT进行无状态认证
    • 用户名密码登录
    • 令牌生成与验证
  2. 用户注册
    • 新用户注册
    • 角色分配(用户、管理员、版主)
  3. 权限控制
    • 基于角色的访问控制
    • 方法级别的权限注解
    • 不同角色访问不同端点
  4. 安全配置
    • CSRF保护禁用(适合REST API)
    • CORS配置
    • 会话管理设置为无状态
  5. 异常处理
    • 统一的异常处理机制
    • 自定义错误消息

4. 使用说明

  1. 启动应用:运行AuthApplication主类
  2. 访问H2控制台:http://localhost:8080/h2-console
  3. API端点
    • 登录:POST /api/auth/signin
    • 注册:POST /api/auth/signup
    • 测试端点:
      • GET /api/test/all - 公开访问
      • GET /api/test/user - 需要认证
      • GET /api/test/mod - 需要MODERATOR角色
      • GET /api/test/admin - 需要ADMIN角色

5. 扩展建议

  1. 添加刷新令牌功能
  2. 实现密码重置功能
  3. 添加验证码支持
  4. 实现OAuth2登录(Google, Facebook等)
  5. 添加审计日志
  6. 实现IP白名单/黑名单

http://www.lryc.cn/news/624846.html

相关文章:

  • redis-集成prometheus监控(k8s)
  • 【K8s】harbor安装与推送镜像
  • 中断线程化
  • 虚幻基础:动作时间窗
  • 徕芬的冰火两重天:增长困局,转型阵痛还是衰落前奏?
  • SQL注入防御
  • 【168页PPT】IBM五粮液集团数字化转型项目实施方案建议书(附下载方式)
  • 力扣2道dp
  • Dijkstra和多层图 0
  • [NSSCTF 2022 Spring Recruit]rrrsssaaa
  • 决策树学习报告
  • 决策树简单实战
  • 容器化 Android 开发效率:cpolar 内网穿透服务优化远程协作流程
  • 【Langchain系列三】GraphGPT——LangChain+NebulaGraph+llm构建智能图数据库问答系统
  • Swift + Xcode 开发环境搭建终极指南
  • 一个月内快速掌握蓝牙原理与应用的全面学习规划
  • 104、【OS】【Nuttx】【周边】文档构建渲染:安装 Sphinx 扩展(上)
  • Day7--滑动窗口与双指针--1695. 删除子数组的最大得分,2958. 最多 K 个重复元素的最长子数组,2024. 考试的最大困扰度
  • 负载均衡终极指南:从流量分发到云原生架构的核心解析
  • Apache IoTDB集群部署实战:1C2D架构的高性能时序数据库搭建与优化指南
  • 第4章-04-用WebDriver页面元素操作
  • onRequestHide at ORIGIN_CLIENT reason HIDE_SOFT_INPUT fromUser false
  • 告别 DOM 的旧时代:从零重塑 Web 渲染的未来
  • scikit-learn/sklearn学习|弹性网络ElasticNet解读
  • LINUX 818 shell:random;for for
  • 咨询进阶——解读咨询顾问技能模型
  • 2025 年世界职业院校技能大赛汽车制造与维修赛道高职组资讯整合
  • Unity开发中的浅拷贝与深拷贝
  • 做一个答题pk小程序多少钱?
  • Golang資源分享