JWT实现接口拦截

举报
多米诺的古牌 发表于 2021/12/30 12:12:15 2021/12/30
【摘要】 1.背景在业务对接中,可能会出现需要外部接口访问后端接口的情况,那么既要放开权限,又要设置一定的拦截机制,本例中通过JWT相关技术生产的token来进行实现拦截与校验(单点登录中的身份校验)。2.简介JWT是Json web token的简称, 是为了在网络应用环境间传递声明而执行的一种基于JSON的开放标准。设计理念是紧凑且安全的,特别适用于分布式站点的单点登录场景。JWT的声明一般被用来...

1.背景

在业务对接中,可能会出现需要外部接口访问后端接口的情况,那么既要放开权限,又要设置一定的拦截机制,本例中通过JWT相关技术生产的token来进行实现拦截与校验(单点登录中的身份校验)。

2.简介

JWT是Json web token的简称, 是为了在网络应用环境间传递声明而执行的一种基于JSON的开放标准。设计理念是紧凑且安全的,特别适用于分布式站点的单点登录场景。JWT的声明一般被用来在身份提供者和服务提供者间传递被认证的用户身份信息,以便于从资源服务器获取资源,也可以增加一些额外的其它业务逻辑所必须的声明信息,也可直接应用于身份认证。

3.JWT的鉴权流程

3.1 用户使用用户名密码来请求服务器或者在没有登录的情况下设置一个获取token的接口,约定好通过一些信息来生产token(此时可进行相关业务自定义设置,跳过3.2和3.3进行自定义生产token);

3.2 服务器进行验证用户的信息;

3.3 服务器通过验证后发送给用户一个随机生产的token;

3.4 客户端存储token,并在每次请求时附送上这个token值;

3.5 服务端通过拦截器拦截所有相关请求,并且验证token值是否正确,如果正确再进行相关接口的处理然后返回相应的数据。

4.代码实现

4.1 首先引入依赖

<!-- jwt  -->
<dependency>
    <groupId>com.auth0</groupId>
    <artifactId>java-jwt</artifactId>
    <version>3.4.0</version>
</dependency>
4.2 写一个JWT鉴权和生产token的工具类

public class JWTUtil {
    private static final String KEY="自定义秘钥";  //秘钥
        //创建token
    public static String getToken(传入对应的实体类T entity){
        Calendar instance = Calendar.getInstance();
        instance.add(Calendar.MINUTE,60);  //这里的时间是根据相关业务自行配置的过期时间
        //创建jwt  builder
        JWTCreator.Builder builder = JWT.create();
        //创建payload
        builder.withClaim("id",T.getId());//这里的自行配置
        builder.withClaim("xxx",T.getXXX());//这里的自行配置

        String token = builder.withExpiresAt(instance.getTime())  //指定令牌过期时间
                .sign(Algorithm.HMAC256(KEY));//指定令牌的加密算法
        return token;
    }
       // 验证token并获取信息
    public static DecodedJWT verify(String token){
        return JWT.require(Algorithm.HMAC256(KEY)).build().verify(token);
    }


}

4.3 放开后端权限

如果后端有鉴权的需要放开权限,将需要放开的接口整理到一起后,统一加上相应的标识如/api/xxx,然后放开这个标识下的所有接口的访问

httpSecurity.antMatchers("/test/api/**").permitAll()

4.4 定义拦截器

@Configuration
public class InterceptorConfig implements WebMvcConfigurer {
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(new JWTInterceptor())
                .addPathPatterns("/test/api/**"); //添加拦截路径,可以加多个
                .excludePathPatterns("/test/api/getToken");//跳过哪个路径,以实际项目为准
    }
}

4.5 定义发送token的接口和配置接口鉴权

4.5.1 获取token的方法

/**
 * 获取token
 * @return
 */
@GetMapping("/getToken")
public JSONObject  getToken(相应的实体类T t){
    JSONObject jsonObject=new JSONObject();

    if (t == null || StringUtils.isBlank(t.getXXX)){//这里根据业务自行配置需要什么字段或者属性来生产token
        return XXX;
    }else{
        String token = JWTUtil.getToken(t);
        jsonObject.put("token",token);
        return jsonObject;
    }
}

4.5.2 鉴权并使用

可以单独放token,或者放进Vo中,本例放入的是请求头中。

@PostMapping("/getXXX")
public XXX getXXX(@RequestBody 相应实体类T t, HttpServletRequest request) {
    if(request ==null || StringUtils.isBlank(request.getHeader("token"))){
        return RestResult.error("获取Token失败!");
    }
    try
    {
        JWTUtil.verify(request.getHeader("token"));
        //XXX相关业务代码
        return XXX;
    }catch (TokenExpiredException e) {
        return RestResult.error("Token已经过期!");
    } catch (SignatureVerificationException e){
        return RestResult.error("签名错误!");
    } catch (AlgorithmMismatchException e){
        return RestResult.error("加密算法不匹配!");
    } catch (Exception e) {
        e.printStackTrace();
        return RestResult.error(e.getMessage());
    }
}

以上就是实现外部接口访问后端进行鉴权的过程,通过约定的字段来进行配置从而生成token,放开后端对应的需要访问的接口,再通过拦截器拦截这些接口的请求,对请求头或者约定在那哪里的token进行鉴权,如果通过则进行后续的业务请求返回业务数据。

【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。