java后端工程师+AI大模型进修ing(研一版‖day59)

今日总结

  • java随笔录------网关认证,为什么使用Spring Security来获取用户身份,而不是用Threadlocal来直接获取呢
  • AI随探录------
  • 代码随想录------组合问题2(回溯去重)

目录

今日总结

详细内容

java随笔录

[为什么使用Spring Security来获取用户身份,而不是用Threadlocal来直接获取呢?](#为什么使用Spring Security来获取用户身份,而不是用Threadlocal来直接获取呢?)

网关认证

AI随探录

代码随想录

组合问题2(回溯去重)


详细内容

java随笔录

为什么使用Spring Security来获取用户身份,而不是用Threadlocal来直接获取呢?

首先,Spring Security是一个专门为Java应用程序提供安全服务的框架,它内置了一系列成熟的安全机制。在获取用户身份时,Spring Security会对用户的凭证进行严格的验证和加密处理,确保只有经过授权的用户才能访问应用程序。

例如,在基于OAuth 2.0的身份验证场景中,Spring Security可以处理复杂的令牌验证和用户信息提取过程,防止令牌被篡改或伪造。

同时,Spring Security提供了一套统一的配置和管理方式,通过配置文件或注解可以方便地定义不同的安全策略。当应用程序的安全需求发生变化时,只需要修改相应的配置即可,而不需要对大量的业务代码进行修改。

ThreadLocal只是一个线程级别的变量存储机制,它本身并不具备任何安全验证功能。如果直接使用ThreadLocal来存储用户身份信息,开发者需要自己实现身份验证和授权逻辑,这很容易引入安全漏洞。并且,ThreadLocal是一个独立的Java类,它与其他框架或服务的集成性较差。

网关认证

所有访问微服务的请求都要经过网关,在网关进行用户身份的认证可以将很多非法的请求拦截到微服务以外,这叫做网关认证。

1、在网关工程添加依赖

XML 复制代码
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-security</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-oauth2</artifactId>
</dependency>
<dependency>
    <groupId>org.projectlombok</groupId>
    <artifactId>lombok</artifactId>
</dependency>
<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>fastjson</artifactId>
</dependency>

2、在properties文件中进行白名单配置,放行认证地址,公开访问地址

3、编写网关过滤

java 复制代码
package com.xuecheng.gateway.config;

import com.alibaba.fastjson.JSON;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.Ordered;
import org.springframework.core.io.buffer.DataBuffer;
import org.springframework.http.HttpStatus;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.security.oauth2.common.OAuth2AccessToken;
import org.springframework.security.oauth2.common.exceptions.InvalidTokenException;
import org.springframework.security.oauth2.provider.token.TokenStore;
import org.springframework.stereotype.Component;
import org.springframework.util.AntPathMatcher;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

import java.io.InputStream;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;
import java.util.Set;

/**
 * @author Mr.M
 * @version 1.0
 * @description 网关认证过虑器
 * @date 2022/9/27 12:10
 */
@Component
@Slf4j
public class GatewayAuthFilter implements GlobalFilter, Ordered {


    //白名单
    private static List<String> whitelist = null;

    static {
        //加载白名单
        try (
                InputStream resourceAsStream = GatewayAuthFilter.class.getResourceAsStream("/security-whitelist.properties");
        ) {
            Properties properties = new Properties();
            properties.load(resourceAsStream);
            Set<String> strings = properties.stringPropertyNames();
            whitelist= new ArrayList<>(strings);

        } catch (Exception e) {
            log.error("加载/security-whitelist.properties出错:{}",e.getMessage());
            e.printStackTrace();
        }


    }

    @Autowired
    private TokenStore tokenStore;


    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        String requestUrl = exchange.getRequest().getPath().value();
        AntPathMatcher pathMatcher = new AntPathMatcher();
        //白名单放行
        for (String url : whitelist) {
            if (pathMatcher.match(url, requestUrl)) {
                return chain.filter(exchange);
            }
        }

        //检查token是否存在
        String token = getToken(exchange);
        if (StringUtils.isBlank(token)) {
            return buildReturnMono("没有认证",exchange);
        }
        //判断是否是有效的token
        OAuth2AccessToken oAuth2AccessToken;
        try {
            oAuth2AccessToken = tokenStore.readAccessToken(token);

            boolean expired = oAuth2AccessToken.isExpired();
            if (expired) {
                return buildReturnMono("认证令牌已过期",exchange);
            }
            return chain.filter(exchange);
        } catch (InvalidTokenException e) {
            log.info("认证令牌无效: {}", token);
            return buildReturnMono("认证令牌无效",exchange);
        }

    }

    /**
     * 获取token
     */
    private String getToken(ServerWebExchange exchange) {
        String tokenStr = exchange.getRequest().getHeaders().getFirst("Authorization");
        if (StringUtils.isBlank(tokenStr)) {
            return null;
        }
        String token = tokenStr.split(" ")[1];
        if (StringUtils.isBlank(token)) {
            return null;
        }
        return token;
    }




    private Mono<Void> buildReturnMono(String error, ServerWebExchange exchange) {
        ServerHttpResponse response = exchange.getResponse();
        String jsonString = JSON.toJSONString(new RestErrorResponse(error));
        byte[] bits = jsonString.getBytes(StandardCharsets.UTF_8);
        DataBuffer buffer = response.bufferFactory().wrap(bits);
        response.setStatusCode(HttpStatus.UNAUTHORIZED);
        response.getHeaders().add("Content-Type", "application/json;charset=UTF-8");
        return response.writeWith(Mono.just(buffer));
    }


    @Override
    public int getOrder() {
        return 0;
    }
}

AI随探录

代码随想录

组合问题2(回溯去重)

本题最终要的思想是去重。考虑到一般的去重方法在回溯中会超时,所以采用数组进行树层去重,区别于树根去重。

给定一个候选人编号的集合 candidates 和一个目标数 target ,找出 candidates 中所有可以使数字和为 target 的组合。

candidates 中的每个数字在每个组合中只能使用 一次

**注意:**解集不能包含重复的组合。

示例 1:

复制代码
输入: candidates = [10,1,2,7,6,1,5], target = 8,
输出:
[
[1,1,6],
[1,2,5],
[1,7],
[2,6]
]

示例 2:

复制代码
输入: candidates = [2,5,2,1,2], target = 5,
输出:
[
[1,2,2],
[5]
]

提示:

  • 1 <= candidates.length <= 100
  • 1 <= candidates[i] <= 50
  • 1 <= target <= 30
java 复制代码
class Solution {
    List<List<Integer>> result = new ArrayList<>();
    List<Integer> path = new LinkedList<>();
    int[] abc = new int[10000];
    private void back(int[] candidates, int target, int ids, int sum,int[] abc) {
        if(sum > target)
        return;
        if(sum == target) {
            result.add(new ArrayList(path));
            return;
        }
        for(int i = ids; i < candidates.length; i++) {
            if (sum + candidates[i] > target) break;
            if(i > 0 && candidates[i - 1] == candidates[i]  && abc[i - 1] == 0)
            continue;
            path.add(candidates[i]);
            abc[i] = 1;
            sum += candidates[i];
            back(candidates,target,i + 1,sum,abc);
            sum -= candidates[i];
            abc[i] = 0;
            path.removeLast();
        }

    }

    public List<List<Integer>> combinationSum2(int[] candidates, int target) {
        Arrays.sort(candidates);
        back(candidates,target,0,0,abc);
        return result;
    }
}
相关推荐
稚辉君.MCA_P8_Java35 分钟前
在Java中,将`Short`(包装类)或`short`(基本类型)转换为`int`
java·开发语言
木易 士心36 分钟前
Node.js 性能诊断利器 Clinic.js:原理剖析与实战指南
开发语言·javascript·node.js
武子康37 分钟前
Java-182 OSS 权限控制实战:ACL / RAM / Bucket Policy 与错误排查
java·数据库·阿里云·云计算·oss·fastdfs·fdfs
天赐学c语言37 分钟前
12.2 - LRU缓存 && C语言内存布局
c++·算法·lru·内存布局
报错小能手37 分钟前
C++流类库 概述及流的格式化输入/输出控制
开发语言·c++
2301_7890156239 分钟前
C++:list(带头双向链表)增删查改模拟实现
c语言·开发语言·c++·list
深圳佛手40 分钟前
Consul热更新的原理与实现
java·linux·网络
扣脚大汉在网络42 分钟前
关于一句话木马
开发语言·网络安全