【手摸手,带你搭建前后端分离商城系统】03 整合Spring Security token 实现方案,完成主业务登录 (2)

Springboot 对于全局异常的处理、简直是简单的不得了~

@RestControllerAdvice @Slf4j public class GlobalExControllerHandler { /** * <p>全局异常拦截器,拦截自定义ApiException * <p>author: <a href='http://www.likecs.com/mailto:maruichao52@gmail.com'>MRC</a> * * @param e 自定义异常 * @return xyz.chaobei.common.api.CommonResult * @since 2020/10/20 **/ @ExceptionHandler(value = ApiException.class) public CommonResult exceptionHandler(ApiException e) { log.info("系统异常拦截器:异常信息:" + e.getMessage()); if (Objects.nonNull(e.getErrorCode())) { return CommonResult.failed(e.getErrorCode()); } return CommonResult.failed(e.getMessage()); } }

直接通过 return 的方式,就好像我们在 controller 里面给前端返回json 一样简单。

断言则是,判断某一条件是否成立、如果不成立则抛出异常的一种更加简单的方式。就不用每次都写throw new xxxException

简而言之就是:一种非常优美的方式抛异常(偷懒的)

public class Asserts { /** * <p>断言抛出一个异常 * <p>author: <a href='http://www.likecs.com/mailto:maruichao52@gmail.com'>MRC</a> * * @param message 提示语 * @return void * @since 2020/10/15 **/ public static void fail(String message) { throw new ApiException(message); } public static void fail(IErrorCode iErrorCode) { throw new ApiException(iErrorCode); } } Spring Security UserDetails

Spring UserDetails 作为一个接口、规定了一些需要的参数方法。我们必须要用自己的逻辑实现这个方法。并将username password 等重要信息通过其定义的方法进行返回。也是作为一种桥接、将我们的用户名、密码等信息交付给 SpringSecurity

public class UmsAdminUserDetails implements UserDetails { private final UmsAdminModel adminModel; public UmsAdminUserDetails(UmsAdminModel adminModel) { this.adminModel = adminModel; } // 省略,具体请查看源码 } JWT 签发服务

JWT 又称作JsonWebToken ,我们需要一个依赖来生成token/登录后需要将这个 token 返回给前端,让前端保存,而后所有的请求都需要带上这个 token 然后我们服务端就知道是哪个用户在请求了。

<dependency> <groupId>io.jsonwebtoken</groupId> <artifactId>jjwt</artifactId> </dependency> 生成token

我在上面的内容里面已经介绍了。我们的token 必须要包含:

sub 签发给谁

iat 过期时间戳

iss 谁签发的

/** * 功能描述: 通过负载生成token * * @Param: claims 负载 * @Return: java.lang.String * @Author: MRC * @Date: 2020/10/21 0:17 */ private String buildToken(Map<String, Object> claims) { return Jwts.builder() .setClaims(claims) .setExpiration(generateExpirationDate()) .signWith(SignatureAlgorithm.HS512, jwtConfig.getSecret()) .compact(); }

通过builder() 构造器、设置其负载内容、并且指定 过期时间setExpiration ,以及加入秘钥进行加密 signWith

token 检验

token 检验包含:当前token 是否有效(能顺利从token取出我们的sub)、以及检验其是否过期 无效等。

/** * <p>从toKen中获取负载信息 * <p>author: <a href='http://www.likecs.com/mailto:maruichao52@gmail.com'>MRC</a> * * @param token 获取的token * @return io.jsonwebtoken.Claims * @since 2020/10/22 **/ private Claims getClaimsFromToken(String token) { Claims claims = null; try { claims = Jwts.parser() .setSigningKey(jwtConfig.getSecret()) .parseClaimsJws(token) .getBody(); } catch (Exception e) { log.info("JWT格式验证失败:{}", token); } return claims; }

该方法描述了如何从一个token 里面取出我们所需要的 Claims 信息。并且可以从负载里面取出 sub 以及 exp 等信息。我简要介绍一个。其他的详细内容请查看源码。

/** * <p>首先获取token当中的负载、而后从负载中取出sub * <p>author: <a href='http://www.likecs.com/mailto:maruichao52@gmail.com'>MRC</a> * * @param token 被校验的token * @return java.lang.String * @since 2020/10/22 **/ public String getUserNameFromToken(String token) { String username; try { Claims claims = getClaimsFromToken(token); username = claims.getSubject(); } catch (Exception e) { username = null; } return username; }

如果你的token被篡改了,那么验证的时候肯定会报错、所以要捕获一下异常。返回空即可。

login service

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/zyjdzd.html