Spring Boot集成Spring Security系列七之接口异常处理

290 阅读2分钟

一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第19天,点击查看活动详情

大家好,我是程序员路飞,三年的下水道打杂前端,喜欢研究技术,正在往全栈发展
欢迎小伙伴们加我微信:DZHningmeng,一起讨论,期待与大家共同成长🥂

前言

这是Spring Boot集成Spring Security的第六章,我将会通过这个系列文章,包括完整的项目搭建、编码过程实现(认证和授权),关键点讲解,来帮助大家了解Spring Security在实际项目中的应用

今天这篇内容是捕获全局接口的统一异常

源码链接

往期系列

Spring Boot集成Spring Security系列一之搭建项目

Spring Boot集成Spring Security系列二之查询用户

Spring Boot集成Spring Security系列三之自定义登录

Spring Boot集成Spring Security系列四之接口鉴权

Spring Boot集成Spring Security系列五之Redis持久化缓存

Spring Boot集成Spring Security系列六之缓存操作异常

功能实现

需求

本篇文章通过捕获全局接口的统一异常(通用和业务性质的),返回给前端展示

  • 通用的比如参数的校验,抛出username is required的信息给前端
  • 业务性质的比如userstatus0,抛出user is locked的信息给前端

编码

编写全局异常处理类

package com.example.springsecurity.common.exception;


import com.example.springsecurity.common.api.IErrorCode;

/**
 * 自定义API异常
 * Created by Lu Fei on 2022/04/20.
 */
public class ApiException extends RuntimeException {
    private String errorCode;
    private String errorMessage;

    public ApiException(IErrorCode errorCode) {
        this.errorCode = errorCode.getCode();
        this.errorMessage = errorCode.getMessage();
    }

    public ApiException(String message) {
        super(message);
    }

    public ApiException(Throwable cause) {
        super(cause);
    }

    public ApiException(String message, Throwable cause) {
        super(message, cause);
    }

    public String getErrorCode() {
        return errorCode;
    }

    public String getErrorMessage() {
        return errorMessage;
    }
}
package com.example.springsecurity.common.exception;

import com.example.springsecurity.common.api.CommonResult;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;

@RestControllerAdvice
public class GlobalExceptionHandler {

    @ExceptionHandler(value = ApiException.class)
    public CommonResult handle(ApiException e) {
        if(e.getErrorCode() != null) {
            return new CommonResult(e.getErrorCode(), e.getErrorMessage());
        }

        return CommonResult.failed();
    }

}

修改UserServiceImpl

定义接口参数断言工具类

package com.example.springsecurity.common.exception;

import com.example.springsecurity.common.api.IErrorCode;
import org.springframework.util.StringUtils;

public class ApiExceptionAsserts {
    public static void hasText(String text, IErrorCode errorCode) {
        if(!StringUtils.hasText(text)) {
            throw new ApiException(errorCode);
        }
    }
}
public String login(String username, String password) {

    ApiExceptionAsserts.hasText(username, UserResultCode.USERNAME_REQUIRED);
    ApiExceptionAsserts.hasText(password, UserResultCode.PASSWORD_REQUIRED);

    String token = null;

    try {
        UserDetails userDetails = userDetailsService.loadUserByUsername(username);
        System.out.println(userDetails.toString());
        if(!passwordEncoder.matches(password, userDetails.getPassword())){
            throw new BadCredentialsException("密码不正确");
        }
        UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities());
        SecurityContextHolder.getContext().setAuthentication(authentication);
        token = jwtTokenUtil.generateToken(userDetails);
    } catch (Exception e) {
        e.printStackTrace();
        LOGGER.warn("登录异常: {}", e.getMessage());
    }
    return token;
}

验证

启动项目

  • 没有username的情况

image.png image.png

  • 没有password的情况

image.png

  • user status为0的情况

数据库修改adminstatus为0

image.png

image.png

小结

这篇文章我们实现了接口的统一异常处理,结合案例讲解,可以应用到实际的生成中。

🚴‍♀️ 结束语

通过项目实践,结合具体的步骤,输出相关的文章,给小伙伴一些有些的知识点,希望大家喜欢我的文章,希望认识到更多志同道合的伙伴,如果你也对技术感兴趣,可以加我好友互相探讨一起进步

Github: Cheering-baby

公众号: 程序员路飞

vx: DZHningmeng

最后,如果喜欢我的文章,可以给个赞👍或者关注➕都是对我最大的支持