Token-过滤器-拦截器-全局异常处理器-OSS-本地存储

Token(JWT)

前期准备:

<!-- JWT依赖-->
<dependency>
    <groupId>io.jsonwebtoken</groupId>
    <artifactId>jjwt</artifactId>
    <version>0.9.1</version>
</dependency>


jdk9版本及以上可能会出现报错需要添加一下三个坐标:
1.这些依赖项将添加 javax.xml.bind.DatatypeConverter 类的实现,并解决在Java 9或更高版本中出现的 ClassNotFoundException 错误。
<dependency>
    <groupId>javax.xml.bind</groupId>
    <artifactId>jaxb-api</artifactId>
    <version>2.3.1</version>
</dependency>
<dependency>
    <groupId>com.sun.xml.bind</groupId>
    <artifactId>jaxb-core</artifactId>
    <version>2.3.0.1</version>
</dependency>
<dependency>
    <groupId>com.sun.xml.bind</groupId>
    <artifactId>jaxb-impl</artifactId>
    <version>2.3.1</version>
</dependency>
如果需要使用JSONObject导入这个坐标
<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>fastjson</artifactId>
    <version>1.2.76</version>
</dependency>

实例代码:

/**
 * JwtUtils类,用于生成和解析JWT
 */
public class JwtUtils {

    // JWT密钥
    private static String jwt = "woshibaba";
    // JWT过期时间(毫秒)
    private static Long expire = 36000000L;

    /**
     * 生成JWT
     * @param map 包含声明的键值对Map
     * @return 生成的JWT字符串
     */
    public static String generateJwt(Map<String,Object> map){
        // 使用HS256签名算法和密钥jwt生成JWT
        String compact = Jwts.builder()
                .addClaims(map)
                .signWith(SignatureAlgorithm.HS256,jwt)
                .setExpiration(new Date(System.currentTimeMillis()+expire))
                .compact();
        return compact;
    }

    /**
     * 解析JWT
     * @param jwts 待解析的JWT字符串
     * @return 解析出的声明对象
     */
    public static Claims parsJwt(String jwts){
        // 使用密钥jwt和HS256签名算法验证JWT签名,并解析出声明
        Claims body = Jwts.parser()
                .setSigningKey(jwt)
                .parseClaimsJws(jwts)
                .getBody();
        return body;
    }
}

过滤器(Filter)

前期准备:

基于SpringMVC实现的
<dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
</dependency>
如果需要使用JSONObject导入这个坐标
<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>fastjson</artifactId>
    <version>1.2.76</version>
</dependency>

示例代码:

使用前需要在主启动类上加上@ServletComponentScan注解
@ServletComponentScan
/** 
 * LoginCheckFilter类,用于检查用户登录状态 
 */ 
@WebFilter(urlPatterns = "/*") 
@Slf4j 
public class LoginCheckFilter implements Filter { 
    /** 
     * 过滤器的doFilter方法,用于检查用户登录状态 
     * @param servletRequest 表示HTTP请求对象 
     * @param servletResponse 表示HTTP响应对象 
     * @param filterChain 表示过滤器链 
     * @throws IOException 
     * @throws ServletException 
     */ 
    @Override 
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException { 
        // 将ServletRequest和ServletResponse对象转换为HttpServletRequest和HttpServletResponse对象 
        HttpServletRequest httpServletRequest= (HttpServletRequest) servletRequest; 
        HttpServletResponse httpServletResponse= (HttpServletResponse) servletResponse; 
        // 打印日志,表示拦截到了请求 
        log.info("Filter:{}","拦截到了"); 
        // 获取请求的URL 
        String url = httpServletRequest.getRequestURL().toString(); 
        // 如果请求的URL包含"login",则放行 
        if(url.contains("login")){ 
            filterChain.doFilter(servletRequest,servletResponse); 
            return; 
        } 
        // 否则,获取请求头中的token 
        String token = httpServletRequest.getHeader("token"); 
        // 如果token为空,表示用户未登录 
        if(token==null){ 
            log.error("LoginCheckFilter:{}","未登录"); 
            // 将错误信息封装成Result对象,并转换成JSON格式字符串 
            Result<Object> log = Result.error("NOT_LOGIN"); 
            String json = JSONObject.toJSONString(log); 
            // 配置响应格式和编码格式 
            httpServletResponse.setContentType("application/json;charset=utf-8"); 
            // 向客户端发送JSON格式字符串 
            httpServletResponse.getWriter().write(json); 
            return; 
        } 
        // 否则,使用JWT工具类解析token 
        try { 
            JwtUtils.parsJwt(token); 
        } catch (Exception e) { 
            // 如果解析失败,表示token不合法 
            log.error("JwtUtils.parsJwt(token)解析失败{}",e.getLocalizedMessage()); 
            // 将错误信息封装成Result对象,并转换成JSON格式字符串 
            Result<Object> error = Result.error(e.getLocalizedMessage()); 
            String json = JSONObject.toJSONString(error); 
            // 配置响应格式和编码格式 
            httpServletResponse.setContentType("application/json;charset=utf-8"); 
            // 向客户端发送JSON格式字符串 
            httpServletResponse.getWriter().write(json); 
            return; 
        } 
        // 如果token合法,放行请求 
        filterChain.doFilter(servletRequest,servletResponse); 
    } 
}

拦截器(Interceptor)

前期准备

他是基于Spring实现的
<dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
</dependency>
如果需要使用JSONObject导入这个坐标
<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>fastjson</artifactId>
    <version>1.2.76</version>
</dependency>

登录校验拦截器

@Component // 声明该类为Spring组件,可以被Spring自动扫描并注入依赖
@Slf4j // 使用Lombok注解,自动生成日志对象
public class LoginCheckInterceptor implements HandlerInterceptor { // 实现HandlerInterceptor接口,用于拦截HTTP请求并检查用户是否已通过身份验证
     @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        // 在控制器处理请求之前拦截请求,并进行身份验证
         String url = request.getRequestURL().toString(); // 获取请求的URL
        if(url.contains("login")){ // 如果请求的URL包含"login",说明用户正在登录,直接放行
            return true;
        }
         String token = request.getHeader("token"); // 获取请求头中的"token"字段,用于身份验证
        log.info("Interceptor:{}","拦截到了"); // 记录日志,表示拦截到了请求
        if(token==null){ // 如果请求头中没有"token"字段,说明用户未登录,返回错误信息并拦截请求
            log.error("LoginCheckFilter:{}","未登录"); // 记录错误日志,表示用户未登录
            Result<Object> log = Result.error("NOT_LOGIN"); // 创建一个Result对象,表示未登录错误
            String json = JSONObject.toJSONString(log); // 将Result对象转换为JSON字符串
            response.setContentType("application/json;charset=utf-8"); // 设置响应的Content-Type为JSON格式
            response.getWriter().write(json); // 向客户端发送错误消息
            return false; // 拦截请求
        }
         try {
            JwtUtils.parsJwt(token); // 使用JwtUtils类的parsJwt方法解析令牌,如果解析失败会抛出异常
        } catch (Exception e) {
            log.error("JwtUtils.parsJwt(token)解析失败{}",e.getLocalizedMessage()); // 记录错误日志,表示令牌无效
            Result<Object> log = Result.error(e.getLocalizedMessage()); // 创建一个Result对象,表示令牌无效错误
            String json = JSONObject.toJSONString(log); // 将Result对象转换为JSON字符串
            response.setContentType("application/json;charset=utf-8"); // 设置响应的Content-Type为JSON格式
            response.getWriter().write(json); // 向客户端发送错误消息
            return false; // 拦截请求
        }
        return true; // 身份验证通过,放行请求
    }
}

注册配置拦截器

@Configuration // 声明该类为Spring配置类,用于配置应用程序上下文
public class LoginWebIntercepter implements WebMvcConfigurer { // 实现WebMvcConfigurer接口,用于配置Web应用程序
     @Autowired // 自动注入LoginCheckInterceptor对象
    LoginCheckInterceptor loginCheckInterceptor;
     @Override
    public void addInterceptors(InterceptorRegistry registry) {
        // 添加拦截器,用于拦截HTTP请求并进行身份验证
        registry.addInterceptor(loginCheckInterceptor) // 添加LoginCheckInterceptor拦截器
                .addPathPatterns("/**") // 对所有请求进行拦截
                .excludePathPatterns("/login"); // 排除/login请求,因为该请求用于用户登录
    }
}

全局异常处理器

前期准备:

创建handler包
他是基于Spring实现的
<dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
</dependency>

示例代码:

@RestControllerAdvice // 声明该类为全局异常处理类,用于统一处理应用程序中的异常
@Slf4j // 使用Lombok的@Slf4j注解,自动生成日志对象
public class GlobalExceptionProcessor extends RuntimeException{
    // 继承RuntimeException类,表示该类本身也是一个异常类型
     @ExceptionHandler(RuntimeException.class) // 声明该方法用于处理RuntimeException类型的异常
    public Result runtimeException(RuntimeException e){
        log.info("RuntimeException:{}",e.getLocalizedMessage()); // 记录异常信息到日志中
        return Result.error(e.getLocalizedMessage()); // 返回一个Result对象,表示处理结果
    }
}

对象存储(OSS)(创建获取:https://editor.csdn.net/md/?articleId=131270244)

前期准备:

  1. 在properties文件中配置阿里OSS
#- endpoint       //阿里云OSS域名
#- accessKeyID    //用户身份ID
#- accessKeySecret   //用户密钥
#- bucketName      //存储空间的名字
aliyun.oss.endpoint=https://oss-cn-****.aliyuncs.com
aliyun.oss.accessKeyId=LTAI4*******6nEuW
aliyun.oss.accessKeySecret=yBshY******KpyqSL
aliyun.oss.bucketName=web-tlias
  1. 配置yml
# 注意! 冒号(:)后有一个空格不要忘记
aliyun:
	oss:
		endpoint: 阿里云OSS域名
		accessKeyId: 用户身份ID
		accessKeySecret: 用户密钥
		bucketName: 存储空间的名字

两种:properties和yml(根据项目需求使用)!!!

注解使用:@ConfigurationProperties("aliyun.oss"):可以代替@Value 跟简单

  • @Value注解只能一个一个的进行外部属性的注入。
  • @ConfigurationProperties可以批量的将外部的属性配置注入到bean对象的属性中。

代码示例:

@Component
//@ConfigurationProperties("aliyun.oss")两种可以任意选择(二选一)
public class AliOssUtils {
    @Value("${aliyun.oss.endpoint}")
    private String endpoint; //OSS的访问域名
    @Value("${aliyun.oss.accessKeyId}")
    private String accessKeyId; //OSS的Access Key ID
    @Value("${aliyun.oss.accessKeySecret}")
    private String accessKeySecret; //OSS的Access Key Secret
    @Value("${aliyun.oss.bucketName}")
    private String bucketName; //OSS的Bucket名称
    /**
     * 实现上传图片到OSS
     */
    public String upload(MultipartFile multipartFile) throws IOException {
        // 获取上传的文件的输入流
        InputStream inputStream = multipartFile.getInputStream();
        // 避免文件覆盖
        String originalFilename = multipartFile.getOriginalFilename();
//       在前面拼接的这个tlias是你在仓库中定义的文件夹
        String fileName =  "tlias/"+ UUID.randomUUID().toString() + originalFilename.substring(originalFilename.lastIndexOf(".")); //生成唯一的文件名
        //上传文件到 OSS
        OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret); //创建OSS客户端
        ossClient.putObject(bucketName, fileName, inputStream); //上传文件
        //文件访问路径
        String url = endpoint.split("//")[0] + "//" + bucketName + "." + endpoint.split("//")[1] + "/" + fileName; //拼接文件访问路径
        // 关闭ossClient
        ossClient.shutdown(); //关闭OSS客户端
        return url; //把上传到OSS的路径返回
    }
}

本地存储

前期准备:

也可以模仿OSS中的代码
将路径提取到properties和yml文件中

代码示例:

* @param username 用户名
 * @param age 年龄
 * @param image 图片文件
 * @return 返回上传后的图片URL
 * @throws IOException IO异常
 */
@PostMapping("/upload")
public Result ossInsertIOURl(String username, Integer age, MultipartFile image) throws IOException {
    //判断上传文件是否为空或者是否大于2M
    if (image.isEmpty() || image.getSize() > 2097152) {
        return Result.error("输入文件大于2M");
    }
    // 获取文件名后缀
    String originalFilename = image.getOriginalFilename();
    String suffix = originalFilename.substring(originalFilename.lastIndexOf("."));
    // 生成UUID作为文件名
    UUID uuid = UUID.randomUUID();
    // 拼接文件路径(将图片位置放在Nginx中html项目下:否则访问不到)
    String filePath = "D:/Java/tlias-web-nginx/nginx-1.22.0-tlias/nginx-1.22.0-tlias/html/images/" + uuid + suffix;
    // 创建文件对象
    File destFile = new File(filePath);
    //判断文件是否存在或者为空
    if (destFile.exists() || destFile == null) {
        return Result.error("文件路径为空");
    }
    // 将上传的文件保存到本地
    image.transferTo(destFile);
    // 拼接图片URL
    String url = "./images/" + uuid + suffix;
    // 返回上传后的图片URL
    return Result.success(url);
}
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
根据提供的引用内容,sentinel-token-server是用于实现集群流控的一种机制。在使用sentinel进行集群流控时,需要将所有的dubbo服务端注册到sentinel控制台,并确保它们的-Dproject.name的值相同,或者启动类的名字相同。如果项目是springcloud,可以不加-Dproject.name配置,默认使用服务名称。如果不是springcloud,可以通过修改sentinel-core中的SentinelConfigLoader来配置。同时,需要监听TokenServer的nameSpace的名称,通过监听token-server-cluster-map中的内容来动态配置token-server的地址和等待transport端口分配。 #### 引用[.reference_title] - *1* *2* [【sentinel】sentinel 集群流控中的Token Server与Token Client的含义(七)](https://blog.csdn.net/s1441101265/article/details/107639852)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^control_2,239^v3^insert_chatgpt"}} ] [.reference_item] - *3* [Sentinel-基于Curator、Apollo实现高可用独立模式TokenServer部署下的集群限流](https://blog.csdn.net/hosaos/article/details/101639320)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^control_2,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值