Java面试常见问题:如何实现基于JWT的登录认证

createh52个月前 (02-01)技术教程8

前文《Java面试常见问题:JWT是什么?》介绍了会话管理常用的JWT(JSON Web Token)标准,JWT在实现web项目的登录认证及授权是非常常用的。

我们先回顾下JWT的请求流程:

  1. 浏览器向服务器发送POST请求,带有用户名和密码
  2. 服务器验证通过后用密钥创建一个JWT字符串
  3. 服务器返回JWT传给浏览器(客户端)
  4. 浏览器再次请求,将JWT放在请求头中
  5. 服务器验证JWT签名,提取用户信息
  6. 服务器返回响应

下面我们就来讲一下Springboot实现JWT认证的过程。

引入JWT依赖

我们可以基于JWT的原理自行实现,不过更方便的做法是引入JWT实现的依赖。jwt.io 网站上列出了不同编程语言的JWT实现,其中com.auth0 是一种基于java语言的常用JWT实现。


      com.auth0
      java-jwt
      3.4.0

自定义注解

我们希望通过对token的验证来控制客户端对服务器方法的访问控制,那么在每次客户端请求到来以后,都要做一个token验证。为了避免将token验证的代码逻辑重复地放在每一个服务端方法中,我们可以通过注解来实现对token的验证。

@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface UserLoginToken {
    boolean required() default true;
}

上面代码定义了一个注解 @UserLoginToken,可以用来修饰方法,也可以用来修饰类,比如Controller。

@UserLoginToken
@GetMapping("/getMessage")
public String getMessage(){
    return "你已通过验证";
}

getMessage()方法上面加上了注解@UserLoginToken,必须需要token才能访问。

登录获取token

显然登录方法Login() 是不需要注解的。登录的逻辑就是首先验证用户名和密码,如果验证通过,那么就调用JWT库的方法来生成token。

@Service("TokenService")
public class TokenService {
    public String getToken(User user){
        String token = "";
        token = JWT.create().withAudience(user.getId())
            .sign(Algorithm.HMAC256(user.getPassword()));
        return token;
    }
}

以上代码使用HMAC-SHA256算法生成token, 密钥就是用户存在服务端数据库中的密码。

withAudience() 将用户ID存入到token中,这样以后服务端收到带有token的请求,就可以从token中提取出用户ID,知道用户是谁了。

拦截器

有了注解还不够,还要有对注解进行处理的拦截器。要实现拦截器,就要继承HandlerInterceptor 接口。

public class AuthenticationInterceptor implements HandlerInterceptor {
    @Autowired
    UserService userService;
    @Override
    public boolean preHandle(HttpServletRequest httpServletRequest, 
                   HttpServletResponse httpServletResponse, Object object) throws Exception {
     ... ... 
    }

HandlerInterceptor接口主要定义了三个方法:

  • boolean preHandle ():预处理回调方法;
  • void postHandle():后处理回调方法, DispatcherServlet进行视图返回渲染之前进行调用;
  • void afterCompletion(): 整个请求处理完毕回调方法, 在DispatcherServlet渲染了对应的视图之后执行。

对于认证拦截,我们只需要实现preHandle() 方法即可,即在方法调用前就验证token,如果没有token或token无效,那么都不允许调用。

拦截器的主要流程:

  1. 从 http 请求头中取出 token;
  2. 判断是否映射到方法;
  3. 检查是否有 @UserLoginToken 注解,没有则跳过认证拦截器;
  4. 如果有 @UserLoginToken 注解,则需要对oken进行验证;
  5. 认证通过则可以访问,不通过则返回相关错误信息。

配置拦截器

最后我们还要通过配置类将已经实现好的拦截器配置生效。

@Configuration
public class InterceptorConfig extends WebMvcConfigurerAdapter {
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(authenticationInterceptor())
                .addPathPatterns("/**");   
    }
    @Bean
    public AuthenticationInterceptor authenticationInterceptor() {
        return new AuthenticationInterceptor();
    }
}

WebMvcConfigurerAdapter 该抽象类中有很多没有具体实现的空方法,我们不必去实现那些我们不用的方法。在这里我们仅需要对 addInterceptors() 方法重写(Override)即可。

我会持续更新关于物联网、云原生以及数字科技方面的文章,用简单的语言描述复杂的技术,也会偶尔发表一下对IT产业的看法,请大家多多关注,欢迎留言和转发,希望与大家互动交流,谢谢。

相关文章

Java Web项目发布,服务器部署(完整版)

作者:席海斌链接:https://blog.csdn.net/xi_haibin/article/details/82348774本文章只为帮助大家学习项目的发布,为基础篇,在此给大家示范在windo...

Jsp Servlet Mysql实现的Java Web在线商城项目源码附运行视频

今天给大家演示一款由jsp servlet MySQL实现的在线商城系统,本系统实现了管理员管理用户、商品(商品分类)、订单、留言、新闻等功能,系统项目源代码在【猿来入此】获取!前台会员注册登录,查看...

腾讯T4专家用1200个实例讲明白了Java Web项目实战,学完月入30K

内容简介《Java Web开发实战1200例》包括第一卷、第二卷共计1200个例子,每卷各计600个例子。本书以开发人员在项目开发中经常遇到的问题和必须掌握的技术为中心,介绍了应用Java Web进行...

我把公司 10 年老系统改造 Maven,真香

公司有几个老古董项目,应该是 10 年前开发的了,有一个是 JSP + Servlet,有一个还用的 SSH 框架,打包用的 Ant,是有多老啊,我想在座的各位很多都没听过吧。为了持续集成、持续部署的...

解放双手!接私活必备的Java开源项目

开源最前线(ID:OpenSourceTop) 猿妹整编项目地址:https://github.com/zhangdaiscott/jeecg-boot今天,猿妹要和大家分享一个 Java 项目快速开...

推荐4个很棒的Java项目,超级适合小白练手,赶紧收藏!

好程序员今天给大家推荐4个很棒的Java练手项目,超适合小白哦~需要源码的,后台dd吧~一、 网上订餐管理系统经过对订餐软件的研究、使用,切身体会用户的需求再对商家展开一系列调查,确定商家的需求。基于...