JAVA:Web安全防御

news2025/4/23 20:33:15

目录

一、Web安全基础与常见威胁

  1. OWASP Top 10核心漏洞解析 • SQL注入(SQLi)、跨站脚本(XSS)、跨站请求伪造(CSRF) • 不安全的反序列化、敏感数据泄露

  2. Java后端常见攻击场景 • 通过HttpServletRequest的请求参数篡改 • JWT令牌伪造与越权访问

  3. 安全防御目标 • 代码层防御(输入校验、输出编码) • 架构层防护(HTTPS、权限控制)


二、认证与授权安全实战

  1. 安全的用户认证方案 • 密码存储:BCrypt算法与盐值加密(Spring Security实现) • 多因素认证(MFA):整合短信/邮箱验证码

  2. OAuth 2.0与JWT安全实践 • 授权码模式防钓鱼攻击 • JWT签名算法选择(HS256 vs RS256)、令牌刷新机制

  3. 细粒度权限控制 • Spring Security的RBAC实现(角色继承、动态权限) • 接口级权限注解(@PreAuthorize("hasRole('ADMIN')")


三、输入校验与数据安全

  1. 请求参数安全处理 • 使用Hibernate Validator进行参数校验(@NotBlank, @Pattern) • 防御SQL注入:MyBatis的#{}占位符 vs ${}拼接风险

  2. XSS防御与输出编码 • Thymeleaf自动转义(th:text vs th:utext) • 自定义HttpServletResponseWrapper过滤敏感数据

  3. 文件上传安全 • 限制文件类型、大小、重命名存储 • 病毒扫描(集成ClamAV)


四、会话管理与通信安全

  1. Session安全防护 • Session固定攻击防御(登录后重置Session ID) • Cookie属性设置(Secure, HttpOnly, SameSite)

  2. HTTPS配置最佳实践 • 免费证书申请(Let's Encrypt) • Spring Boot中强制HTTPS跳转

  3. CSRF防御方案 • Spring Security的CSRF Token机制 • 前后端分离架构下的CSRF防御(双重Cookie验证)


五、API安全与微服务防护

  1. API接口安全设计 • 接口版本控制、限流(Rate Limiting) • 使用Swagger/OAS3生成安全的API文档

  2. 微服务安全架构 • Spring Cloud Gateway的鉴权过滤(JWT解析) • 服务间通信安全(mTLS双向认证)

  3. 第三方API集成风险 • 密钥管理(Vault或KMS动态获取) • 请求签名(HMAC-SHA256)


六、日志监控与应急响应

  1. 安全日志记录 • 敏感操作日志(登录、支付)的审计追踪 • 使用Log4j2/SLF4J标记高风险事件

  2. 异常监控与告警 • 集成Prometheus监控异常请求(如频繁401错误) • 邮件/钉钉通知(通过Spring Boot Actuator)

  3. 漏洞应急响应 • 热修复(Arthas动态修改代码) • 快速回滚(Docker+K8s版本管理)


七、面试高频安全题解析

  1. 经典面试题 • 如何防止JWT令牌被盗用? • 解释Spring Security的过滤器链机制

  2. 场景设计题 • 设计一个安全的用户注册/登录流程 • 如何优化一个存在SQL注入漏洞的老系统?

  3. 陷阱题 • 为什么说@PreAuthorize注解不能完全替代权限校验? • HTTPS能否防御CSRF攻击?为什么?


一、Web安全基础与常见威胁


1. OWASP Top 10核心漏洞解析

1.1 SQL注入(SQLi)

攻击原理:攻击者通过构造恶意输入参数,篡改SQL语句逻辑,实现非授权数据访问或破坏。 • Java代码示例(漏洞场景)

// 错误示例:直接拼接SQL语句  
String sql = "SELECT * FROM users WHERE username = '" + request.getParameter("username") + "'";  
jdbcTemplate.query(sql, ...);  

防御方案: • 预编译语句(PreparedStatement)java String sql = "SELECT * FROM users WHERE username = ?"; jdbcTemplate.query(sql, new Object[]{request.getParameter("username")}, ...);ORM框架防御:使用JPA/Hibernate的命名参数查询: java @Query("SELECT u FROM User u WHERE u.username = :username") User findByUsername(@Param("username") String username);

1.2 跨站脚本(XSS)

攻击原理:用户输入未过滤,恶意脚本被浏览器执行(如窃取Cookie)。 • Java代码示例(漏洞场景)

// 错误示例:直接输出用户输入到HTML  
model.addAttribute("message", request.getParameter("content"));  
<!-- Thymeleaf模板中直接渲染 -->  
<div th:text="${message}"></div>  

防御方案: • 输出编码:Thymeleaf自动转义(默认启用): html <!-- 安全写法 --> <div th:text="${message}"></div> <!-- 危险写法(避免使用) --> <div th:utext="${message}"></div>自定义过滤器:对特殊字符(<, >, &)进行转义: java String safeOutput = StringEscapeUtils.escapeHtml4(rawInput);

1.3 跨站请求伪造(CSRF)

攻击原理:诱导用户点击恶意链接,以用户身份执行非授权操作(如转账)。 • 防御方案: • Spring Security默认防护:自动生成CSRF Token并校验。 java // 启用CSRF防护(默认开启) http.csrf().csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse());前端集成:在表单或Header中携带Token: html <input type="hidden" th:name="${_csrf.parameterName}" th:value="${_csrf.token}"/>

1.4 不安全的反序列化

攻击原理:恶意序列化数据触发远程代码执行(如Apache Commons Collections漏洞)。 • 防御方案: • 白名单校验:使用Jackson的@JsonTypeInfo限制反序列化类: java @JsonTypeInfo(use = Id.NAME, property = "type") @JsonSubTypes({@Type(value = SafeClass.class, name = "safe")}) public abstract class BaseClass {}JVM参数限制:禁止危险类的反序列化: bash -Djdk.serialFilter=!org.apache.commons.collections4.*

1.5 敏感数据泄露

攻击场景: • 日志中打印用户密码(logger.info("User password: {}", password))。 • API响应中暴露数据库字段(如返回User实体所有属性)。 • 防御方案: • DTO隔离敏感字段java public class UserDto { private String username; // 不包含password字段 }Spring Boot配置:屏蔽敏感信息的日志输出: yaml logging: level: org.springframework: INFO pattern: console: "%d %-5level [%thread] %logger{36} - %msg%n" filter: deny: password,secret


2. Java后端常见攻击场景

2.1 通过HttpServletRequest的请求参数篡改

场景示例:用户修改URL中的id参数越权访问他人数据:

GET /api/orders/123 → 篡改为 GET /api/orders/456  

防御方案: • 权限校验:在Service层验证数据归属: java public Order getOrder(Long orderId) { Order order = orderRepository.findById(orderId); if (!order.getUserId().equals(currentUserId())) { throw new AccessDeniedException("无权访问"); } return order; }

2.2 JWT令牌伪造与越权访问

攻击原理:窃取JWT令牌或伪造签名访问他人数据。 • 防御方案: • 强签名算法:使用RS256(非对称加密)而非HS256(对称加密): yaml # application.yml jwt: algorithm: RS256 public-key: classpath:public_key.pem令牌失效机制:维护令牌黑名单(Redis记录失效Token): java // 登出时加入黑名单 redisTemplate.opsForValue().set("jwt:invalid:" + token, "1", 5, TimeUnit.MINUTES); // 校验时检查黑名单 if (redisTemplate.hasKey("jwt:invalid:" + token)) { throw new InvalidTokenException("Token已失效"); }


3. 安全防御目标

3.1 代码层防御

输入校验:在Controller层拦截非法参数:

@PostMapping("/users")  
public ResponseEntity<?> createUser(@Valid @RequestBody UserCreateRequest request) {  
    // 校验通过后才执行业务逻辑  
    return ResponseEntity.ok(userService.create(request));  
}  

输出编码:全局配置JSON序列化转义:

@Bean  
public Jackson2ObjectMapperBuilderCustomizer jsonEscape() {  
    return builder -> builder.featuresToEnable(JsonWriteFeature.ESCAPE_NON_ASCII);  
}  
3.2 架构层防护

HTTPS强制启用

@Configuration  
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {  
    @Override  
    protected void configure(HttpSecurity http) throws Exception {  
        http.requiresChannel().anyRequest().requiresSecure();  
    }  
}  

权限控制:基于角色的接口访问控制:

@PreAuthorize("hasRole('ADMIN')")  
@DeleteMapping("/users/{id}")  
public void deleteUser(@PathVariable Long id) {  
    userService.delete(id);  
}  

总结

漏洞本质:信任未经验证的外部输入。 • 防御核心: • 不信任原则:所有输入均需校验,所有输出均需编码。 • 最小权限原则:用户只能访问必需资源。 • 开发习惯:使用安全框架(如Spring Security)而非手动造轮子,定期依赖扫描(Maven Dependency Check)。


二、认证与授权安全实战


1. 安全的用户认证方案

1.1 密码存储:BCrypt算法与盐值加密

为何选择BCrypt: • 抗彩虹表攻击:BCrypt自动生成随机盐值(Salt),相同密码哈希值不同。 • 计算成本可调:通过strength参数控制哈希迭代次数(默认10,约100ms)。 • Spring Security集成

@Configuration  
public class SecurityConfig extends WebSecurityConfigurerAdapter {  
    @Bean  
    public PasswordEncoder passwordEncoder() {  
        return new BCryptPasswordEncoder(12);  // 强度参数12(2^12次迭代)  
    }  
}  

密码存储示例

// 用户注册时加密密码  
String rawPassword = "user123";  
String encodedPassword = passwordEncoder().encode(rawPassword);  
userRepository.save(new User(username, encodedPassword));  
1.2 多因素认证(MFA)整合

短信验证码流程

  1. 用户输入用户名密码完成初步认证。

  2. 生成6位随机码存入Redis(5分钟过期)。

    String code = String.format("%06d", new Random().nextInt(999999));  
    redisTemplate.opsForValue().set("mfa:" + username, code, 5, TimeUnit.MINUTES);  
  3. 调用短信服务商API发送验证码到用户手机。

  4. 用户提交验证码,系统校验通过后发放Token。

Spring Security扩展点

public class MfaAuthenticationFilter extends UsernamePasswordAuthenticationFilter {  
    @Override  
    public Authentication attemptAuthentication(HttpServletRequest request,  
            HttpServletResponse response) throws AuthenticationException {  
        // 验证短信验证码逻辑  
        String code = request.getParameter("code");  
        String cachedCode = redisTemplate.opsForValue().get("mfa:" + username);  
        if (!code.equals(cachedCode)) {  
            throw new BadCredentialsException("验证码错误");  
        }  
        return super.attemptAuthentication(request, response);  
    }  
}  

2. OAuth 2.0与JWT安全实践

2.1 授权码模式防钓鱼攻击

PKCE(Proof Key for Code Exchange)扩展: • 流程: 1. 客户端生成code_verifier(随机字符串)和code_challenge(其SHA256哈希)。 2. 授权请求携带code_challenge。 3. 令牌请求时提交code_verifier,服务端验证哈希一致性。 • 防御场景:防止授权码被中间人劫持后用于获取Token。 • Spring Security配置

@Bean  
public AuthorizationServerSettings authorizationServerSettings() {  
    return AuthorizationServerSettings.builder()  
            .pkceRequired(true)  // 强制启用PKCE  
            .build();  
}  
2.2 JWT安全配置

签名算法选择

算法类型安全性建议
HS256对称加密仅限内部服务
RS256非对称加密公开API(推荐)
JWT密钥管理
// 使用RSA密钥对(2048位)  
@Bean  
public KeyPair keyPair() {  
    return KeyPairGenerator.getInstance("RSA").generateKeyPair();  
}  
@Bean  
public JwtDecoder jwtDecoder(KeyPair keyPair) {  
    return NimbusJwtDecoder.withPublicKey((RSAPublicKey) keyPair.getPublic()).build();  
}  

令牌刷新机制: • Refresh Token有效期:设置较长周期(如7天),但需绑定设备指纹。 • 刷新接口防护java @PostMapping("/token/refresh") public ResponseEntity<JwtResponse> refreshToken(@RequestParam String refreshToken) { // 校验refreshToken有效性及设备指纹 if (!deviceService.validate(refreshToken, currentDeviceId)) { throw new InvalidTokenException("无效的Refresh Token"); } // 生成新Access Token return ResponseEntity.ok(jwtService.refreshToken(refreshToken)); }


3. 细粒度权限控制

3.1 RBAC与动态权限实现

数据库表设计

CREATE TABLE role (  
  id BIGINT PRIMARY KEY,  
  name VARCHAR(20) NOT NULL UNIQUE  
);  
CREATE TABLE permission (  
  id BIGINT PRIMARY KEY,  
  resource VARCHAR(50) NOT NULL,  
  action VARCHAR(10) NOT NULL  -- 如read, write  
);  
CREATE TABLE role_permission (  
  role_id BIGINT,  
  permission_id BIGINT,  
  PRIMARY KEY (role_id, permission_id)  
);  

动态权限加载

@Component  
public class DynamicPermissionService implements PermissionEvaluator {  
    @Override  
    public boolean hasPermission(Authentication auth, Object target, Object permission) {  
        // 从数据库查询用户权限  
        List<String> permissions = permissionService.getPermissions(auth.getName());  
        return permissions.contains(permission.toString());  
    }  
}  
3.2 接口级权限控制

注解使用示例

  @PreAuthorize("hasPermission(#id, 'USER', 'READ')")  
  @GetMapping("/users/{id}")  
  public User getUser(@PathVariable Long id) {  
      return userService.findById(id);  
  }  

  @PreAuthorize("hasRole('ADMIN') or hasPermission(#request, 'WRITE')")  
  @PostMapping("/users")  
  public void createUser(@RequestBody UserCreateRequest request) {  
      userService.create(request);  
  }  

角色继承配置

@Bean  
public RoleHierarchy roleHierarchy() {  
    RoleHierarchyImpl hierarchy = new RoleHierarchyImpl();  
    hierarchy.setHierarchy("ROLE_ADMIN > ROLE_STAFF \n ROLE_STAFF > ROLE_USER");  
    return hierarchy;  
}  

总结与面试要点

高频面试题: • 如何防止JWT令牌被盗用:绑定IP/设备指纹、设置短有效期、使用Refresh Token轮换。 • OAuth2授权码模式流程:客户端重定向→用户授权→授权码→换Token。 • 安全红线: • 禁止在URL中传递敏感参数(如response_type=token隐式模式)。 • 生产环境禁用ROLE_ANONYMOUS接口。

代码规范检查项: • 使用@PreAuthorize而非手动校验权限。 • 所有API文档(Swagger)标记所需权限。

通过分层权限控制与安全协议加固,构建可扩展、易维护的认证授权体系。


三、输入校验与数据安全


1. 请求参数安全处理

1.1 Hibernate Validator参数校验实战

常用校验注解

注解功能示例
@NotBlank非空且至少一个非空格字符@NotBlank String username
@Pattern正则表达式校验@Pattern(regexp = "^1[3-9]\\d{9}$") String phone
@Size字符串/集合长度限制@Size(min=6, max=20) String password
@Email邮箱格式校验@Email String email

全局异常处理:统一返回校验失败信息

@RestControllerAdvice  
public class GlobalExceptionHandler {  
    @ExceptionHandler(MethodArgumentNotValidException.class)  
    public ResponseEntity<?> handleValidationException(MethodArgumentNotValidException ex) {  
        Map<String, String> errors = new HashMap<>();  
        ex.getBindingResult().getFieldErrors().forEach(error ->  
            errors.put(error.getField(), error.getDefaultMessage())  
        );  
        return ResponseEntity.badRequest().body(errors);  
    }  
}  
1.2 MyBatis SQL注入防御

#{}${}的区别

占位符处理方式安全性适用场景
#{}预编译参数化查询动态条件值
${}直接拼接SQL片段低(需严格校验)动态表名/排序字段

安全示例

  <!-- 安全写法(使用#{}) -->  
  <select id="findUser" resultType="User">  
      SELECT * FROM users WHERE username = #{username}  
  </select>  

  <!-- 危险写法(避免使用${}) -->  
  <select id="findUser" resultType="User">  
      SELECT * FROM users WHERE username = '${username}'  
  </select>  

动态表名处理:若必须使用${},需白名单过滤:

public void checkTableName(String tableName) {  
    if (!Arrays.asList("users", "orders").contains(tableName)) {  
        throw new IllegalArgumentException("非法表名");  
    }  
}  

2. XSS防御与输出编码

2.1 Thymeleaf自动转义机制

安全输出

  <!-- 自动转义特殊字符 -->  
  <div th:text="${userInput}"></div>  

  <!-- 危险:直接渲染原始HTML -->  
  <div th:utext="${userInput}"></div>  

禁用部分标签:防止富文本XSS

@Bean  
public SpringTemplateEngine templateEngine() {  
    SpringTemplateEngine engine = new SpringTemplateEngine();  
    engine.setEnableSpringELCompiler(true);  
    // 配置HTML过滤器,仅允许安全标签  
    Set<String> allowedTags = new HashSet<>(Arrays.asList("div", "span", "p"));  
    engine.addTemplateResolver(new HtmlFilterTemplateResolver(allowedTags));  
    return engine;  
}  
2.2 敏感数据响应过滤

自定义HttpServletResponseWrapper

  public class SensitiveDataResponseWrapper extends HttpServletResponseWrapper {  
      public SensitiveDataResponseWrapper(HttpServletResponse response) {  
          super(response);  
      }  

      @Override  
      public PrintWriter getWriter() throws IOException {  
          return new PrintWriter(new OutputStreamWriter(getOutputStream())) {  
              @Override  
              public void write(String s) {  
                  // 过滤身份证号(示例)  
                  String filtered = s.replaceAll("\\d{17}[\\dXx]", "***");  
                  super.write(filtered);  
              }  
          };  
      }  
  }  

注册过滤器

@Bean  
public FilterRegistrationBean<SensitiveDataFilter> sensitiveDataFilter() {  
    FilterRegistrationBean<SensitiveDataFilter> bean = new FilterRegistrationBean<>();  
    bean.setFilter(new SensitiveDataFilter());  
    bean.addUrlPatterns("/*");  
    return bean;  
}  

3. 文件上传安全实战

3.1 基础防护策略

Spring Boot配置限制

spring:  
  servlet:  
    multipart:  
      max-file-size: 10MB      # 单文件最大10MB  
      max-request-size: 100MB  # 总请求最大100MB  

文件类型白名单

  public boolean isAllowedFileType(String filename) {  
      String extension = FilenameUtils.getExtension(filename).toLowerCase();  
      return Arrays.asList("jpg", "png", "pdf").contains(extension);  
  }  

  @PostMapping("/upload")  
  public String uploadFile(@RequestParam("file") MultipartFile file) {  
      if (!isAllowedFileType(file.getOriginalFilename())) {  
          throw new InvalidFileTypeException("不支持的文件类型");  
      }  
      // 保存文件逻辑  
  }  
3.2 病毒扫描集成(ClamAV)

ClamAV客户端配置

  @Bean  
  public ClamAVClient clamAVClient() {  
      return new ClamAVClient("clamav-server", 3310);  
  }  

  public boolean scanFile(byte[] fileData) {  
      try {  
          ClamAVClient client = clamAVClient();  
          return client.scan(fileData).isClean();  
      } catch (IOException e) {  
          throw new VirusScanException("病毒扫描失败");  
      }  
  }  

上传流程整合

@PostMapping("/upload-safe")  
public ResponseEntity<?> uploadSafeFile(@RequestParam("file") MultipartFile file) {  
    if (!scanFile(file.getBytes())) {  
        throw new VirusDetectedException("文件包含恶意代码");  
    }  
    // 保存安全文件  
}  

总结与最佳实践

输入校验铁律: • 前端非信任:即使前端已校验,后端必须二次验证。 • 边界防御:在数据进入系统时(Controller层)立即校验。 • XSS防御层级

  1. 输入过滤:拒绝含<script>标签的内容。

  2. 输出编码:模板引擎自动转义。

  3. CSP策略Content-Security-Policy: default-src 'self'。 • 文件安全原则

• **隔离存储**:上传文件存放到非Web根目录。  
• **权限控制**:设置文件系统权限(如Linux的`chmod 644`)。  

代码自查清单: • 所有用户输入是否经过校验? • 所有输出到页面的数据是否经过编码? • 文件上传接口是否限制类型、扫描病毒?

通过分层防御策略,构建从输入到输出的完整安全链条。


四、会话管理与通信安全


1. Session安全防护

1.1 Session固定攻击防御

攻击原理:攻击者诱导用户使用已知的Session ID登录,从而劫持用户会话。 • 防御方案:用户认证成功后立即重置Session ID。

@PostMapping("/login")  
public String login(HttpServletRequest request) {  
    // 认证成功后使旧Session失效  
    request.getSession().invalidate();  
    HttpSession newSession = request.getSession(true);  
    // 存储用户认证信息到新Session  
    newSession.setAttribute("user", authenticatedUser);  
    return "redirect:/dashboard";  
}  
1.2 Cookie属性强化

Spring Security配置安全Cookie

  @Bean  
  public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {  
      http  
          .sessionManagement(session ->  
              session.sessionCreationPolicy(SessionCreationPolicy.IF_REQUIRED)  
          )  
          .headers(headers ->  
              headers  
                  .httpStrictTransportSecurity(hsts ->  
                      hsts.includeSubDomains(true).preload(true)  
                  )  
          )  
          .csrf().csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse());  

      // Cookie安全属性  
      http.securityContext().securityContextRepository(new CookieSecurityContextRepository());  
      return http.build();  
  }  

  public class CookieSecurityContextRepository extends HttpSessionSecurityContextRepository {  
      @Override  
      public void saveContext(SecurityContext context, HttpServletRequest request, HttpServletResponse response) {  
          Cookie cookie = new Cookie("JSESSIONID", request.getSession().getId());  
          cookie.setSecure(true);      // 仅HTTPS传输  
          cookie.setHttpOnly(true);   // 禁止JavaScript访问  
          cookie.setAttribute("SameSite", "Lax");  
          response.addCookie(cookie);  
      }  
  }  

关键属性说明

属性作用
SecureCookie仅通过HTTPS传输
HttpOnly防止XSS攻击窃取Cookie
SameSite=Lax限制第三方网站跨站请求携带Cookie(防御CSRF)

2. HTTPS配置最佳实践

2.1 Let's Encrypt免费证书申请

Certbot自动化工具

  # 安装Certbot(Ubuntu示例)  
  sudo apt install certbot python3-certbot-nginx  

  # 申请证书(需提前配置Nginx)  
  sudo certbot --nginx -d yourdomain.com  

  # 自动续期(添加到crontab)  
  0 3 * * * certbot renew --quiet  
2.2 Spring Boot强制HTTPS跳转

application.yml配置

server:  
  ssl:  
    enabled: true  
    key-store: classpath:keystore.p12  
    key-store-password: changeit  
    key-store-type: PKCS12  
    key-alias: tomcat  
  port: 443  

HTTP自动跳转HTTPS

  @Configuration  
  public class HttpsRedirectConfig {  
      @Bean  
      public ServletWebServerFactory servletContainer() {  
          TomcatServletWebServerFactory tomcat = new TomcatServletWebServerFactory() {  
              @Override  
              protected void postProcessContext(Context context) {  
                  SecurityConstraint securityConstraint = new SecurityConstraint();  
                  securityConstraint.setUserConstraint("CONFIDENTIAL");  
                  SecurityCollection collection = new SecurityCollection();  
                  collection.addPattern("/*");  
                  securityConstraint.addCollection(collection);  
                  context.addConstraint(securityConstraint);  
              }  
          };  
          tomcat.addAdditionalTomcatConnectors(httpConnector());  
          return tomcat;  
      }  

      private Connector httpConnector() {  
          Connector connector = new Connector(TomcatServletWebServerFactory.DEFAULT_PROTOCOL);  
          connector.setPort(80);  
          connector.setRedirectPort(443);  
          return connector;  
      }  
  }  

3. CSRF防御方案

3.1 Spring Security CSRF Token机制

默认防御原理: • 服务端生成随机Token(存储在Session或Cookie中)。 • 客户端提交请求时携带Token(表单隐藏字段或请求头)。 • 表单集成示例

<form th:action="@{/transfer}" method="post">  
    <input type="hidden" th:name="${_csrf.parameterName}" th:value="${_csrf.token}"/>  
    <input type="text" name="amount"/>  
    <button type="submit">转账</button>  
</form>  
3.2 前后端分离架构下的CSRF防御

双重Cookie验证方案

  1. 服务端在登录成功后设置一个随机Token到Cookie:

    ResponseCookie cookie = ResponseCookie.from("csrf-token", UUID.randomUUID().toString())  
            .httpOnly(false)  
            .secure(true)  
            .sameSite("Lax")  
            .build();  
    response.addHeader(HttpHeaders.SET_COOKIE, cookie.toString());  
  2. 前端在请求头中携带该Token:

    fetch('/api/transfer', {  
        method: 'POST',  
        headers: {  
            'X-CSRF-TOKEN': getCookie('csrf-token') // 从Cookie读取  
        },  
        body: JSON.stringify({ amount: 100 })  
    });  
  3. 服务端验证Cookie和Header中的Token是否一致:

    String cookieToken = request.getCookies().stream()  
            .filter(c -> "csrf-token".equals(c.getName()))  
            .findFirst()  
            .map(Cookie::getValue)  
            .orElse("");  
    String headerToken = request.getHeader("X-CSRF-TOKEN");  
    if (!cookieToken.equals(headerToken)) {  
        throw new CsrfTokenException("CSRF Token不匹配");  
    }  

总结与实施建议

  1. Session管理: • 启用HttpOnlySecure属性,生产环境强制SameSite=Lax。 • 集群环境下使用Redis集中存储Session。

  2. HTTPS强化: • 启用HSTS头(Strict-Transport-Security)并提交预加载列表。 • 定期监控证书有效期(90天续期)。

  3. CSRF防御组合拳: • 传统Web应用:优先使用Spring Security原生Token机制。 • 前后端分离:采用双重Cookie验证+SameSite组合。

漏洞自查清单: • 所有Cookie是否设置SecureHttpOnly? • 敏感操作(如支付)是否启用双重认证? • 是否禁用HTTP明文传输?

通过协议加固与会话管理,构建可信的端到端安全通信体系。


五、API安全与微服务防护


1. API接口安全设计

1.1 接口版本控制与限流

版本控制: • URL路径版本: ```java @GetMapping("/v1/users/{id}") public UserV1 getUserV1(@PathVariable Long id) { ... }

@GetMapping("/v2/users/{id}")  
public UserV2 getUserV2(@PathVariable Long id) { ... }  
```  

请求头版本java @GetMapping("/users/{id}") public ResponseEntity<?> getUser( @PathVariable Long id, @RequestHeader("Api-Version") String version ) { if ("v2".equals(version)) return UserV2.from(userService.findById(id)); return UserV1.from(userService.findById(id)); }

限流(Rate Limiting): • Spring Cloud Gateway限流yaml spring: cloud: gateway: routes: - id: user-service uri: lb://user-service predicates: - Path=/api/users/** filters: - name: RequestRateLimiter args: redis-rate-limiter.replenishRate: 10 # 每秒允许10个请求 redis-rate-limiter.burstCapacity: 20 # 突发容量 key-resolver: "#{@userKeyResolver}" # 按用户限流自定义限流键解析器java @Bean public KeyResolver userKeyResolver() { return exchange -> Mono.just(exchange.getRequest().getRemoteAddress().getHostName()); }

1.2 安全的API文档(Swagger/OAS3)

隐藏敏感端点

@Operation(hidden = true)  // 隐藏特定接口  
@GetMapping("/internal/users")  
public List<User> getInternalUsers() { ... }  

添加认证参数

@Bean  
public OpenAPI customOpenAPI() {  
    return new OpenAPI()  
        .components(new Components().addSecuritySchemes("JWT",  
            new SecurityScheme().type(SecurityScheme.Type.HTTP)  
                                .scheme("bearer")  
                                .bearerFormat("JWT")  
        ))  
        .info(new Info().title("API文档").version("v1"));  
}  

2. 微服务安全架构

2.1 Spring Cloud Gateway鉴权过滤

JWT解析过滤器

@Component  
public class JwtAuthFilter implements GlobalFilter {  
    @Override  
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {  
        String token = exchange.getRequest().getHeaders().getFirst("Authorization");  
        if (token == null || !token.startsWith("Bearer ")) {  
            exchange.getResponse().setStatusCode(HttpStatus.UNAUTHORIZED);  
            return exchange.getResponse().setComplete();  
        }  
        try {  
            Jws<Claims> claims = Jwts.parserBuilder()  
                .setSigningKey(publicKey)  
                .build()  
                .parseClaimsJws(token.replace("Bearer ", ""));  
            exchange.getAttributes().put("user", claims.getBody().getSubject());  
            return chain.filter(exchange);  
        } catch (JwtException e) {  
            exchange.getResponse().setStatusCode(HttpStatus.UNAUTHORIZED);  
            return exchange.getResponse().setComplete();  
        }  
    }  
}  
2.2 服务间通信安全(mTLS)

生成证书

  # 生成服务端证书  
  keytool -genkeypair -alias server -keyalg RSA -keysize 2048 -storetype PKCS12 -keystore server.p12  

  # 生成客户端证书  
  keytool -genkeypair -alias client -keyalg RSA -keysize 2048 -storetype PKCS12 -keystore client.p12  

  # 导出客户端公钥并导入服务端信任库  
  keytool -exportcert -alias client -keystore client.p12 -file client.cer  
  keytool -importcert -alias client -file client.cer -keystore server-truststore.p12  

Spring Boot配置mTLS

server:  
  ssl:  
    key-store: classpath:server.p12  
    key-store-password: changeit  
    key-alias: server  
    trust-store: classpath:server-truststore.p12  
    trust-store-password: changeit  
    client-auth: need  # 强制双向认证  

3. 第三方API集成风险管控

3.1 密钥动态管理(Vault集成)

Spring Vault配置

spring:  
  vault:  
    uri: https://vault.example.com:8200  
    authentication: TOKEN  
    token: s.xyz123  
    ssl:  
      trust-store: classpath:vault-truststore.p12  
      trust-store-password: changeit  

动态获取API密钥

  @Value("${secrets.api-key}")  
  private String apiKey;  

  public void callThirdPartyAPI() {  
      HttpHeaders headers = new HttpHeaders();  
      headers.set("X-API-Key", apiKey);  
      // 发起请求  
  }  
3.2 请求签名(HMAC-SHA256)

签名生成

public String signRequest(String secret, String method, String path, String body) {  
    String data = method + path + body;  
    Mac sha256 = Mac.getInstance("HmacSHA256");  
    sha256.init(new SecretKeySpec(secret.getBytes(), "HmacSHA256"));  
    byte[] hash = sha256.doFinal(data.getBytes(StandardCharsets.UTF_8));  
    return Base64.getEncoder().encodeToString(hash);  
}  

验证签名

@PostMapping("/api")  
public ResponseEntity<?> handleRequest(  
    @RequestHeader("X-Signature") String signature,  
    @RequestBody String body  
) {  
    String expected = signRequest(apiSecret, "POST", "/api", body);  
    if (!signature.equals(expected)) {  
        throw new InvalidSignatureException("签名验证失败");  
    }  
    // 处理业务逻辑  
}  

总结与面试要点

高频面试题: • 如何防止API被重放攻击:使用时间戳+随机数+签名,服务端校验时间窗口和随机数唯一性。 • mTLS与单向TLS的区别:mTLS要求客户端和服务器都提供证书,双向验证身份。 • 安全红线: • 禁止在代码或配置中硬编码密钥(如String apiKey = "123456";)。 • 生产环境禁用Swagger的enable: true配置。

实施建议: • 分层防御:网关统一鉴权 + 服务间mTLS + 接口级签名。 • 密钥轮换:通过Vault定期自动更新密钥,降低泄露风险。 • 监控告警:对异常签名失败、频繁限流触发进行实时告警。

通过API网关、服务间安全通信和密钥管理,构建端到端的安全防护体系。


六、日志监控与应急响应


1. 安全日志记录

1.1 敏感操作审计追踪

AOP切面记录关键操作

  @Aspect  
  @Component  
  public class AuditLogAspect {  
      @Autowired  
      private AuditLogService auditLogService;  

      @Around("@annotation(auditLog)")  
      public Object logAudit(ProceedingJoinPoint joinPoint, AuditLog auditLog) throws Throwable {  
          String username = SecurityContextHolder.getContext().getAuthentication().getName();  
          String method = joinPoint.getSignature().toShortString();  
          Object result = joinPoint.proceed();  
          // 记录日志到数据库  
          auditLogService.log(username, method, "SUCCESS");  
          return result;  
      }  
  }  

  // 自定义注解标记需要审计的方法  
  @Retention(RetentionPolicy.RUNTIME)  
  @Target(ElementType.METHOD)  
  public @interface AuditLog {  
      String value() default "";  
  }  

  // 使用示例  
  @AuditLog("用户登录")  
  @PostMapping("/login")  
  public void login(@RequestBody LoginRequest request) { ... }  

Log4j2高风险事件标记

<!-- log4j2.xml配置 -->  
<Filters>  
    <RegexFilter regex=".*(login|payment).*" onMatch="ACCEPT" onMismatch="NEUTRAL"/>  
</Filters>  
<Appenders>  
    <Kafka name="SecurityLog" topic="security-log">  
        <PatternLayout pattern="%d %-5p [%t] %c{1.} - %m%n"/>  
    </Kafka>  
</Appenders>  

2. 异常监控与告警

2.1 Prometheus监控异常请求

自定义指标采集

  @Bean  
  public MeterRegistryCustomizer<PrometheusMeterRegistry> configureMetrics() {  
      return registry -> {  
          Counter.builder("http.error.counter")  
                .description("HTTP请求错误计数")  
                .tag("status", "401")  
                .register(registry);  
      };  
  }  

  @ControllerAdvice  
  public class GlobalExceptionHandler {  
      @ExceptionHandler(AuthenticationException.class)  
      public ResponseEntity<?> handleAuthError(AuthenticationException ex) {  
          Metrics.counter("http.error.counter", "status", "401").increment();  
          return ResponseEntity.status(401).body("Unauthorized");  
      }  
  }  

Grafana告警规则配置

# prometheus-alerts.yml  
groups:  
- name: api-alerts  
  rules:  
  - alert: HighUnauthorizedRequests  
    expr: rate(http_error_counter_total{status="401"}[5m]) > 10  
    for: 5m  
    labels:  
      severity: critical  
    annotations:  
      summary: "高频401错误 (实例 {{ $labels.instance }})"  
      description: "5分钟内401错误率超过10次/秒"  
2.2 Spring Boot Actuator告警集成

钉钉机器人告警(WebHook)

  @Component  
  public class DingTalkNotifier {  
      @Autowired  
      private RestTemplate restTemplate;  

      @EventListener  
      public void handleAlert(AlertEvent event) {  
          String message = String.format("告警: %s\n时间: %s",  
                  event.getAlert().getAnnotations().get("summary"),  
                  LocalDateTime.now());  
          restTemplate.postForEntity(  
              "https://oapi.dingtalk.com/robot/send?access_token=xxx",  
              Map.of("msgtype", "text", "text", Map.of("content", message)),  
              String.class  
          );  
      }  
  }  

3. 漏洞应急响应

3.1 Arthas热修复实战

动态修改方法逻辑(无需重启)

  # 1. 附加到目标Java进程  
  $ arthas-boot <PID>  

  # 2. 反编译方法查看当前逻辑  
  arthas> jad com.example.UserService.getUser  

  # 3. 修改方法并编译为字节码  
  arthas> mc -d /tmp /tmp/UserService.java  

  # 4. 重新加载类  
  arthas> redefine /tmp/com/example/UserService.class  

临时禁用危险接口

  # 查找RequestMappingHandlerMapping  
  arthas> sc -d *HandlerMapping  

  # 获取Bean实例ID  
  arthas> get static org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping  

  # 删除指定接口映射  
  arthas> invoke @12345 unregisterMapping '/vulnerable-api'  
3.2 Kubernetes快速回滚

版本标签与回滚命令

  # 查看部署历史版本  
  $ kubectl rollout history deployment/user-service  

  # 回滚到上一版本  
  $ kubectl rollout undo deployment/user-service  

  # 回滚到指定版本  
  $ kubectl rollout undo deployment/user-service --to-revision=2  

Docker镜像回退策略

# 保留旧版本镜像标签(如v1.2.1)  
FROM openjdk:17-alpine  
COPY target/user-service-v1.2.1.jar /app.jar  
CMD ["java", "-jar", "/app.jar"]  
# 快速切换镜像版本  
$ kubectl set image deployment/user-service *=registry.example.com/user-service:v1.2.1  

总结与实施建议

日志监控闭环

  1. 采集:Log4j2/Kafka收集关键日志。

  2. 分析:Prometheus监控指标,ELK聚合日志。

  3. 告警:Grafana阈值告警,钉钉实时通知。 • 应急响应流程

• **优先级**:热修复 > 版本回滚 > 漏洞修复。  
• **演练**:定期模拟攻击场景(如SQL注入),测试响应速度。  

生产检查清单: • 所有敏感操作是否有审计日志? • 监控面板是否覆盖核心指标(QPS、错误率、响应时间)? • 回滚脚本是否经过验证?

工具链推荐: • 日志分析:ELK Stack(Elasticsearch + Logstash + Kibana) • 热修复:Arthas + JVM-Sandbox • 容器管理:Kubernetes + Helm(版本控制)

通过日志监控与自动化应急响应,最小化漏洞影响时间,保障系统持续安全运行。


七、面试高频安全题解析


1. 经典面试题

1.1 如何防止JWT令牌被盗用?

防御措施

  1. HTTPS加密传输:防止中间人窃听令牌。

  2. 短有效期:设置较短的Access Token有效期(如15分钟)。

  3. 绑定设备指纹:Token生成时记录设备信息(IP、User-Agent),校验时匹配。

  4. Refresh Token轮换:每次刷新Token时作废旧Token并生成新Token。

  5. 黑名单机制:登出时将未过期的Token加入Redis黑名单。 • 代码示例

  // Token生成时绑定设备指纹  
  String deviceId = DigestUtils.md5Hex(request.getHeader("User-Agent") + clientIp);  
  claims.put("device", deviceId);  

  // 校验时验证设备信息  
  if (!tokenDeviceId.equals(currentDeviceId)) {  
      throw new InvalidTokenException("设备不匹配");  
  }  
1.2 解释Spring Security的过滤器链机制

核心流程

  1. 过滤器链顺序:按注册顺序依次执行过滤器,每个过滤器处理特定安全任务。

  2. 关键过滤器: ◦ SecurityContextPersistenceFilter:加载SecurityContext(如从Session)。 ◦ UsernamePasswordAuthenticationFilter:处理表单登录。 ◦ BasicAuthenticationFilter:处理HTTP Basic认证。 ◦ FilterSecurityInterceptor:最终决定是否允许访问。 • 自定义扩展

@Configuration  
public class SecurityConfig extends WebSecurityConfigurerAdapter {  
    @Override  
    protected void configure(HttpSecurity http) throws Exception {  
        http.addFilterBefore(new CustomFilter(), UsernamePasswordAuthenticationFilter.class);  
    }  
}  

2. 场景设计题

2.1 设计一个安全的用户注册/登录流程

注册流程

  1. 密码强度校验:至少8位,包含字母、数字、特殊字符。

  2. 邮箱/手机验证:发送验证码并校验。

  3. 密码加密存储:使用BCrypt算法(BCryptPasswordEncoder)。 • 登录流程

  4. 验证码防护:连续失败3次后触发图形验证码。

  5. 双因素认证(2FA):登录后发送短信/邮箱验证码。

  6. Session管理:登录成功后重置Session ID。 • 代码要点

// 登录失败计数器(Redis实现)  
String key = "login_fail:" + username;  
redisTemplate.opsForValue().increment(key);  
if (redisTemplate.opsForValue().get(key) >= 3) {  
    throw new CaptchaRequiredException("需要验证码");  
}  
2.2 如何优化存在SQL注入漏洞的老系统?

分步方案

  1. 代码审查:全局搜索${}拼接的SQL语句。

  2. 紧急修复: ◦ 将${}替换为#{}(MyBatis)。 ◦ 添加输入白名单校验(如字段名、排序方向)。

  3. 长期优化: ◦ 引入ORM框架(如JPA/Hibernate)。 ◦ 数据库权限最小化(只读账号用于查询)。 • 监控措施

-- 开启数据库审计日志  
SET GLOBAL general_log = 'ON';  
-- 分析日志中的可疑SQL(如连续多次SELECT *)  

3. 陷阱题

3.1 为什么@PreAuthorize不能完全替代权限校验?

答案本质: • 声明式校验局限性@PreAuthorize仅校验接口访问权限,无法覆盖数据级权限。 • 业务逻辑校验缺失:例如用户A只能修改自己的订单,需在Service层二次验证。 • 代码反例

@PreAuthorize("hasRole('USER')")  
@PutMapping("/orders/{id}")  
public void updateOrder(@PathVariable Long id) {  
    // 未校验当前用户是否拥有该订单  
    orderService.update(id);  
}  
3.2 HTTPS能否防御CSRF攻击?为什么?

正确答案: • 不能防御:CSRF攻击利用的是浏览器的Cookie自动携带机制,与通信是否加密无关。 • 防御依赖: 1. CSRF Token:服务端生成随机Token并校验。 2. SameSite Cookie:设置为LaxStrict模式(禁止跨域携带Cookie)。 • 补充场景

<!-- 恶意网站构造表单 -->  
<form action="https://bank.com/transfer" method="POST">  
  <input type="hidden" name="amount" value="1000">  
  <input type="hidden" name="to" value="attacker">  
</form>  
<!-- 用户已登录bank.com,Cookie自动携带 -->  

总结与面试技巧

回答结构

  1. 直接回答:先给出明确结论(如“不能防御”)。

  2. 技术解析:结合原理说明原因(如HTTPS加密与CSRF机制无关)。

  3. 方案补充:给出正确防御措施(如CSRF Token + SameSite)。 • 高频考点

• **JWT安全**:签名算法选择、Refresh Token设计、黑名单机制。  
• **Spring Security**:过滤器链顺序、自定义鉴权逻辑、OAuth2集成。  
• **应急响应**:日志分析、热修复与回滚策略。  

最终建议:结合具体项目经验,说明实际遇到的挑战与解决方案(如“在XX项目中,我们通过X方法解决了Y安全问题”),展现工程化思维与实战能力。

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

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

相关文章

39.剖析无处不在的数据结构

数据结构是计算机中组织和存储数据的特定方式&#xff0c;它的目的是方便且高效地对数据进行访问和修改。数据结构表述了数据之间的关系&#xff0c;以及操作数据的一系列方法。数据又是程序的基本单元&#xff0c;因此无论是哪种语言、哪种领域&#xff0c;都离不开数据结构&a…

在离线 Ubuntu 环境下部署双 Neo4j 实例(Prod Dev)

在许多开发和生产场景中&#xff0c;我们可能需要在同一台服务器上运行多个独立的 Neo4j 数据库实例&#xff0c;例如一个用于生产环境 (Prod)&#xff0c;一个用于开发测试环境 (Dev)。本文将详细介绍如何在 离线 的 Ubuntu 服务器上&#xff0c;使用 tar.gz 包部署两个 Neo4j…

第十五届蓝桥杯 2024 C/C++组 下一次相遇

目录 题目&#xff1a; 题目描述&#xff1a; 题目链接&#xff1a; 思路&#xff1a; 自己的思路详解&#xff1a; 更好的思路详解&#xff1a; 代码&#xff1a; 自己的思路代码详解&#xff1a; 更好的思路代码详解&#xff1a; 题目&#xff1a; 题目描述&#xf…

【2】CICD持续集成-k8s集群中安装Jenkins

一、背景&#xff1a; Jenkins是一款开源 CI&CD 系统&#xff0c;用于自动化各种任务&#xff0c;包括构建、测试和部署。 Jenkins官方提供了镜像&#xff1a;https://hub.docker.com/r/jenkins/jenkins 使用Deployment来部署这个镜像&#xff0c;会暴露两个端口&#xff…

IDEA 创建Maven 工程(图文)

设置Maven 仓库 打开IDEA 开发工具&#xff0c;我的版本是2024.3.1&#xff08;每个版本的位置不一样&#xff09;。在【Customize】选项中&#xff0c;可以直接设置【语言】&#xff0c;在最下面选择【All setting】。 进入到熟悉的配置界面&#xff0c;选择配置的【setting…

通过C# 将Excel表格转换为图片(JPG/ PNG)

Excel 表格可能会因为不同设备、不同软件版本或字体缺失等问题&#xff0c;导致格式错乱或数据显示异常。转换为图片后&#xff0c;能确保数据的排版、格式和外观始终保持一致&#xff0c;无论在何种设备或平台上查看&#xff0c;都能呈现出固定的样式&#xff0c;避免了因环境…

国产紫光同创FPGA实现SDI视频编解码+图像缩放,基于HSSTHP高速接口,提供2套工程源码和技术支持

目录 1、前言工程概述免责声明 2、相关方案推荐我已有的所有工程源码总目录----方便你快速找到自己喜欢的项目本博已有的 SDI 编解码方案本方案在Xilinx--Artix7系列FPGA上的应用本方案在Xilinx--Kintex系列FPGA上的应用本方案在Xilinx--Zynq系列FPGA上的应用本方案在Xilinx--U…

自动驾驶安全模型研究

自动驾驶安全模型研究 自动驾驶安全模型研究 自动驾驶安全模型研究1.自动驾驶安全模型概述2. 自动驾驶安全模型应用3. 自动驾驶安全模型介绍3.1 Last Point to Steer3.2 Safety Zone3.3 RSS (Responsibility-Sensitive Safety)3.4 SFF (Safety Force Field)3.5 FSM (Fuzzy Safe…

【项目】基于MCP+Tabelstore架构实现知识库答疑系统

基于MCPTabelstore架构实现知识库答疑系统 整体流程设计&#xff08;一&#xff09;Agent 架构&#xff08;二&#xff09;知识库存储&#xff08;1&#xff09;向量数据库Tablestore&#xff08;2&#xff09;MCP Server &#xff08;三&#xff09;知识库构建&#xff08;1&a…

当OCR遇上“幻觉”:如何让AI更靠谱地“看懂”文字?

在数字化的世界里&#xff0c;OCR&#xff08;光学字符识别&#xff09;技术就像给机器装上了“电子眼”。但当这项技术遇上大语言模型&#xff0c;一个意想不到的问题出现了——AI竟然会像人类一样产生“幻觉”。想象一下&#xff0c;当你拿着模糊的财务报表扫描件时&#xff…

Docker用model.config部署及更新多个模型

步骤&#xff1a; 1、本地打包模型 2、编写model.config文件 3、使用 Docker 启动一个 TensorFlow Serving 容器 4、本地打包后的模型修改后&#xff0c;修改本地model.config&#xff0c;再同步更新容器的model.config 1、本地打包模型&#xff08;本地路径&#xff09; 2、…

Linux kernel signal原理(下)- aarch64架构sigreturn流程

一、前言 在上篇中写到了linux中signal的处理流程&#xff0c;在do_signal信号处理的流程最后&#xff0c;会通过sigreturn再次回到线程现场&#xff0c;上篇文章中介绍了在X86_64架构下的实现&#xff0c;本篇中介绍下在aarch64架构下的实现原理。 二、sigaction系统调用 #i…

matlab论文图一的地形区域图的球形展示Version_1

matlab论文图一的地形区域图的球形展示Version_1 图片 此图来源于&#xff1a; ![Jieqiong Zhou, Ziyin Wu, Dineng Zhao, Weibing Guan, Chao Zhu, Burg Flemming, Giant sand waves on the Taiwan Banks, southern Taiwan Strait: Distribution, morphometric relationship…

Flask API 项目 Swagger 版本打架不兼容

Flask API 项目 Swagger 版本打架不兼容 1. 问题背景 在使用 Flask 3.0.0 时遇到以下问题&#xff1a; 安装 flask_restful_swagger 时&#xff0c;它强制将 Flask 降级到 1.1.4&#xff0c;并导致其他依赖&#xff08;如 flask-sqlalchemy、flask-apispec&#xff09;出现版…

基于YOLOv11 和 ByteTrack 实现目标跟踪

介 绍 之前我们介绍了使用YOLOv9与 ByteTrack 结合进行对象跟踪的概念&#xff0c;展示了这两种强大的技术如何有效地协同工作。现在&#xff0c;让我们通过探索与 ByteTrack 结合的 YOLOv11 来进一步了解这一概念。 实战 | 基于YOLOv9和OpenCV实现车辆跟踪计数&#xff08;步骤…

Qt Creator 创建 Qt Quick Application一些问题

一、Qt Creator 创建 Qt Quick Application 时无法选择 MSVC 编译器(即使已安装 Qt 5.15.2 和 MSVC2019) 1、打开 Qt Creator 的编译器设置 工具 (Tools) → 选项 (Options) → Kits → 编译器 (Compilers) 检查是否存在 Microsoft Visual C++ Compiler (x86_amd64) 或类似条…

编码转换器

大批量转换编码 可以将整个工程文件夹从GB18030转为UTF-8 使用Qt C制作 项目背景 比较老的工程&#xff0c;尤其是keil嵌入式的工程&#xff0c;其文本文件&#xff08;.c、.cpp、.h、.txt、……&#xff09;编码为gb2312&#xff0c;这为移植维护等带来了不便。现在uit-8用…

[密码学实战]密评考试训练系统v1.0程序及密评参考题库(获取路径在文末)

[密码学实战]密评考试训练系统v1.0程序及密评参考题库 引言:密评考试的重要性与挑战 商用密码应用安全性评估(简称"密评") 作为我国密码领域的重要认证体系,已成为信息安全从业者的必备技能。根据国家密码管理局最新数据,截至2024年6月,全国仅有3000余人持有…

蓝桥杯常考的找规律题

目录 灵感来源&#xff1a; B站视频链接&#xff1a; 找规律题具有什么样的特点&#xff1a; 报数游戏&#xff08;Java组&#xff09;&#xff1a; 题目描述&#xff1a; 题目链接&#xff1a; 思路详解&#xff1a; 代码详解&#xff1a; 阶乘求和&#xff08;Java组…

MySQL_MCP_Server_pro接入cherry_studio实现大模型操作数据库

大模型直接与数据库交互&#xff0c;实现基本增删改查操作。首先贴下代码地址&#xff1a; https://github.com/wenb1n-dev/mysql_mcp_server_pro 安装环境&#xff1a;win10 1、下载代码 git clone https://github.com/wenb1n-dev/mysql_mcp_server_pro 2、使用conda创建…