广告
返回顶部
首页 > 资讯 > 后端开发 > Python >Java实现Token登录验证的项目实践
  • 644
分享到

Java实现Token登录验证的项目实践

JavaToken登录验证Java登录验证 2023-03-19 18:03:59 644人浏览 安东尼

Python 官方文档:入门教程 => 点击学习

摘要

目录一、Jwt是什么?二、使用步骤1.项目结构2.相关依赖3.数据库4.相关代码三、测试结果一、JWT是什么? 在介绍JWT之前,我们先来回顾一下利用token进行用户身份验证的流程

一、JWT是什么?

在介绍JWT之前,我们先来回顾一下利用token进行用户身份验证的流程:

1、客户端使用用户名和密码请求登录

2、服务端收到请求,验证用户名和密码

3、验证成功后,服务端会签发一个token,再把这个token返回给客户端

4、客户端收到token后可以把它存储起来,比如放到cookie中

5、客户端每次向服务端请求资源时需要携带服务端签发的token,可以在cookie或者header中携带

6、服务端收到请求,然后去验证客户端请求里面带着的token,如果验证成功,就向客户端返回请求数据

这种基于token的认证方式相比传统的session认证方式更节约服务器资源,并且对移动端和分布式更加友好。其优点如下

支持跨域访问:cookie是无法跨域的,而token由于没有用到cookie(前提是将token放到请求头中),所以跨域后不会存在信息丢失问题
无状态:token机制在服务端不需要存储session信息,因为token自身包含了所有登录用户的信息,所以可以减轻服务端压力
更适用CDN:可以通过内容分发网络请求服务端的所有资料
更适用于移动端:当客户端是非浏览器平台时,cookie是不被支持的,此时采用token认证方式会简单很多
无需考虑CSRF:由于不再依赖cookie,所以采用token认证方式不会发生CSRF,所以也就无需考虑CSRF的防御

而JWT就是上述流程当中token的一种具体实现方式,其全称是JSON WEB Token,官网地址:https://jwt.io/

通俗地说,JWT的本质就是一个字符串,它是将用户信息保存到一个Json字符串中,然后进行编码后得到一个JWT token,并且这个JWT token带有签名信息,接收后可以校验是否被篡改,所以可以用于在各方之间安全地将信息作为Json对象传输。JWT的认证流程如下:

1、首先,前端通过Web表单将自己的用户名和密码发送到后端的接口,这个过程一般是一个POST请求。建议的方式是通过SSL加密的传输(HttpS),从而避免敏感信息被嗅探

2、后端核对用户名和密码成功后,将包含用户信息的数据作为JWT的Payload,将其与JWT Header分别进行Base64编码拼接后签名,形成一个JWT Token,形成的JWT Token就是一个如同lll.zzz.xxx的字符串
3、后端将JWT Token字符串作为登录成功的结果返回给前端。前端可以将返回的结果保存在浏览器中,退出登录时删除保存的JWT Token即可

4、前端在每次请求时将JWT Token放入HTTP请求头中的Authorization属性中(解决XSS和XSRF问题)

5、后端检查前端传过来的JWT Token,验证其有效性,比如检查签名是否正确、是否过期、token的接收方是否是自己等等

6、验证通过后,后端解析出JWT Token中包含的用户信息,进行其他逻辑操作(一般是根据用户信息得到权限等),返回结果

在这里插入图片描述

最后:说白了,JWT:jsON Web Token,其实token就是一段字符串,由三部分组成:Header,Payload,Signature

二、使用步骤

1.项目结构

在这里插入图片描述

2.相关依赖

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>Mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>8.0.22</version>
        </dependency>

        <dependency>
            <groupId>cn.hutool</groupId>
            <artifactId>hutool-all</artifactId>
            <version>5.7.21</version>
        </dependency>

        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-boot-starter</artifactId>
            <version>3.4.3.2</version>
        </dependency>

        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>fastjson</artifactId>
            <version>1.2.79</version>
        </dependency>

        <dependency>
            <groupId>commons-beanutils</groupId>
            <artifactId>commons-beanutils</artifactId>
            <version>1.9.4</version>
        </dependency>

        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.18.22</version>
        </dependency>

        <dependency>
            <groupId>commons-io</groupId>
            <artifactId>commons-io</artifactId>
            <version>2.11.0</version>
        </dependency>

        <dependency>
            <groupId>org.apache.poi</groupId>
            <artifactId>poi-ooxml</artifactId>
            <version>4.1.2</version>
        </dependency>

        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.13.1</version>
            <scope>test</scope>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <version>2.3.8.RELEASE</version>
        </dependency>

        <dependency>
            <groupId>com.auth0</groupId>
            <artifactId>java-jwt</artifactId>
            <version>3.18.3</version>
        </dependency>

        <dependency>
            <groupId>org.apache.commons</groupId>
            <artifactId>commons-lang3</artifactId>
        </dependency>
    </dependencies>

3.数据库

这里进行测试,所以用户类只有用户名密码,自行创建

在这里插入图片描述

4.相关代码

1、annotation包
PassToken:

package com.geesun.annotation;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;


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

UserLoginToken:

package com.geesun.annotation;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;



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

2、common包
CodeMsg:

package com.geesun.common;


public class CodeMsg {
    private int retCode;
    private String message;
    // 按照模块定义CodeMsg
    // 通用异常
    public static CodeMsg SUCCESS = new CodeMsg(0,"success");
    public static CodeMsg SERVER_EXCEPTION = new CodeMsg(500100,"服务端异常");
    public static CodeMsg PARAMETER_ISNULL = new CodeMsg(500101,"输入参数为空");
    // 业务异常
    public static CodeMsg USER_NOT_EXSIST = new CodeMsg(500102,"用户不存在");
    public static CodeMsg ONLINE_USER_OVER = new CodeMsg(500103,"在线用户数超出允许登录的最大用户限制。");
    public static CodeMsg SESSION_NOT_EXSIST =  new CodeMsg(500104,"不存在离线session数据");
    public static CodeMsg NOT_FIND_DATA = new CodeMsg(500105,"查找不到对应数据");
    public static CodeMsg USER_OR_PASS_ERROR = new CodeMsg(500102,"账号或者密码错误,请重试!");


    private CodeMsg(int retCode, String message) {
        this.retCode = retCode;
        this.message = message;
    }

    public int getRetCode() {
        return retCode;
    }
    public String getMessage() {
        return message;
    }
    public void setMessage(String message) {
        this.message = message;
    }
}

Result:

package com.geesun.common;


public class Result<T> {

    private String message;
    private int retCode;
    private T data;

    private Result(T data) {
        this.retCode = 200;
        this.message = "成功";
        this.data = data;
    }

    private Result(CodeMsg cm) {
        if(cm == null){
            return;
        }
        this.retCode = cm.getRetCode();
        this.message = cm.getMessage();
    }

    
    public static <T> Result<T> success(T data){
        return new Result<T>(data);
    }

    
    @SuppressWarnings("unchecked")
    public static <T> Result<T> success(){
        return (Result<T>) success("");
    }
    
    public static <T> Result<T> error(CodeMsg cm){
        return new Result<T>(cm);
    }
    
    public static <T> Result<T> error(CodeMsg cm,String msg){
        cm.setMessage(cm.getMessage()+"--"+msg);
        return new Result<T>(cm);
    }
    public T getData() {
        return data;
    }
    public String getMessage() {
        return message;
    }
    public int getRetCode() {
        return retCode;
    }
}

3、config包
InterceptorConfig:

package com.geesun.config;

import com.geesun.Interceptor.AuthenticationInterceptor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.fORMat.FormatterReGIStry;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.validation.MessageCodesResolver;
import org.springframework.validation.Validator;
import org.springframework.web.method.support.HandlerMethodArgumentResolver;
import org.springframework.web.method.support.HandlerMethodReturnValueHandler;
import org.springframework.web.servlet.HandlerExceptionResolver;
import org.springframework.web.servlet.config.annotation.*;
import java.util.List;


@Configuration
public class InterceptorConfig implements WebmvcConfigurer {
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(authenticationInterceptor())
                .addPathPatterns("
public class AuthenticationInterceptor implements HandlerInterceptor {

    @Autowired
    UserService userService;

    @Override
    public boolean preHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object object) throws Exception {
        String token = httpServletRequest.getHeader("token");// 从 http 请求头中取出 token
        // 如果不是映射到方法直接通过
        if(!(object instanceof HandlerMethod)){
            return true;
        }
        HandlerMethod handlerMethod=(HandlerMethod)object;
        Method method=handlerMethod.getMethod();
        //检查是否有passtoken注释,有则跳过认证
        if (method.isAnnotationPresent(PassToken.class)) {
            PassToken passToken = method.getAnnotation(PassToken.class);
            if (passToken.required()) {
                return true;
            }
        }
        //检查有没有需要用户权限的注解
        if (method.isAnnotationPresent(UserLoginToken.class)) {
            UserLoginToken userLoginToken = method.getAnnotation(UserLoginToken.class);
            if (userLoginToken.required()) {
                // 执行认证
                if (token == null) {
                    throw new RuntimeException("无token,请重新登录");
                }
                // 获取 token 中的 user id
                String userId;
                try {
                    userId = JWT.decode(token).getAudience().get(0);
                } catch (JWTDecodeException j) {
                    throw new RuntimeException("401");
                }
                User user = userService.findUserById(userId);
                if (user == null) {
                    throw new RuntimeException("用户不存在,请重新登录");
                }
                // 验证 token
                JWTVerifier jwtVerifier = JWT.require(AlGorithm.HMac256(user.getPassword())).build();
                try {
                    jwtVerifier.verify(token);
                } catch (JWTVerificationException e) {
                    throw new RuntimeException("401");
                }
                return true;
            }
        }
        return true;
    }

    @Override
    public void postHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, ModelAndView modelAndView) throws Exception {

    }
    @Override
    public void afterCompletion(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) throws Exception {

    }
}

5、utils包
TokenUtil:

package com.geesun.utils;

import com.auth0.jwt.JWT;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import javax.servlet.http.HttpServletRequest;


public class TokenUtil {

    public static String getTokenUserId() {
        String token = getRequest().getHeader("token");// 从 http 请求头中取出 token
        String userId = JWT.decode(token).getAudience().get(0);
        return userId;
    }

    
    public static HttpServletRequest getRequest() {
        ServletRequestAttributes requestAttributes = (ServletRequestAttributes) RequestContextHolder
                .getRequestAttributes();
        return requestAttributes == null ? null : requestAttributes.getRequest();
    }

}

6、pojo包
User:

package com.geesun.pojo;

import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

import java.io.Serializable;

@Data
@AllArgsConstructor
@NoArgsConstructor
@TableName(value = "`user`")
public class User implements Serializable {
    @TableId(value = "id", type = IdType.NONE)
    private String id;

    @TableField(value = "username")
    private String username;

    @TableField(value = "passWord")
    private String password;

    private static final long serialVersionUID = 1L;
}

7、controller包
UserController:

package com.geesun.controller;

import cn.hutool.json.JSONObject;
import com.geesun.annotation.UserLoginToken;
import com.geesun.common.CodeMsg;
import com.geesun.common.Result;
import com.geesun.pojo.User;
import com.geesun.service.UserService;
import com.geesun.service.impl.TokenService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletResponse;


@RestController
@RequestMapping("/user")
public class UserController {

    @Autowired
    private UserService userService;

    @Autowired
    private TokenService tokenService;

    
    @UserLoginToken
    @GetMapping("/list")
    public Result<Object> list(){
        return Result.success(userService.list());
    }


    
    @RequestMapping(value = "/login" ,method = RequestMethod.GET)
    public Result<Object> login(User user, HttpServletResponse response) {
        JSONObject jsonObject = new JSONObject();
        //获取用户账号密码
        User userForBase = new User();
        userForBase.setId(userService.findByUsername(user).getId());
        userForBase.setUsername(userService.findByUsername(user).getUsername());
        userForBase.setPassword(userService.findByUsername(user).getPassword());
        //判断账号或密码是否正确
        if (!userForBase.getPassword().equals(user.getPassword())) {
            return Result.error(CodeMsg.USER_OR_PASS_ERROR);
        } else {
            String token = tokenService.getToken(userForBase);
            jsonObject.put("token", token);
            Cookie cookie = new Cookie("token", token);
            cookie.setPath("/");
            response.addCookie(cookie);
            return Result.success(jsonObject);
        }
    }
    
}

8、service包
UserService接口:

package com.geesun.service;

import com.baomidou.mybatisplus.extension.service.IService;
import com.geesun.pojo.User;

public interface UserService extends IService<User> {


    int deleteByIds(Long[] ids);

    int addUser(User user);

    User findByUsername(User user);

    User findUserById(String userId);
}

UserServiceImpl实现类:

package com.geesun.service.impl;

import cn.hutool.core.util.ArrayUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.geesun.mapper.UserMapper;
import com.geesun.pojo.User;
import com.geesun.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.Arrays;

@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {

    @Autowired
    private UserMapper userMapper;
    
    
    public User findByUsername(User user){
        return userMapper.selectOne(new LambdaQueryWrapper<User>().eq(User::getUsername,user.getUsername()));
    }

    public User findUserById(String userId) {
        return userMapper.selectById(userId);
    }

}

TokenService:

package com.geesun.service.impl;

import com.auth0.jwt.JWT;
import com.auth0.jwt.algorithms.Algorithm;
import com.geesun.pojo.User;
import org.springframework.stereotype.Service;
import java.util.Date;


@Service
public class TokenService {

    public String getToken(User user) {
        Date start = new Date();
        long currentTime = System.currentTimeMillis() + 60* 60 * 1000;//一小时有效时间
        Date end = new Date(currentTime);
        String token = "";

        token = JWT.create().withAudience(user.getId()).withIssuedAt(start).withExpiresAt(end)
                .sign(Algorithm.HMAC256(user.getPassword()));
        return token;
    }
}

9、mapper包

package com.geesun.mapper;

import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.geesun.pojo.User;

public interface UserMapper extends BaseMapper<User> {

}

三、测试结果

1、登录验证

在这里插入图片描述

2、查询用户信息
这个方法加上了@UserLoginToken,所以要token才能查询

在这里插入图片描述

在这里插入图片描述

3、不加上Token进行测试就会出错提示

在这里插入图片描述

出错提示:

在这里插入图片描述

到此这篇关于Java实现Token登录验证的项目实践的文章就介绍到这了,更多相关Java Token登录验证内容请搜索编程网以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程网!

--结束END--

本文标题: Java实现Token登录验证的项目实践

本文链接: https://www.lsjlt.com/news/200252.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • Java实现Token登录验证的项目实践
    目录一、JWT是什么?二、使用步骤1.项目结构2.相关依赖3.数据库4.相关代码三、测试结果一、JWT是什么? 在介绍JWT之前,我们先来回顾一下利用token进行用户身份验证的流程...
    99+
    2023-03-19
    Java Token登录验证 Java 登录验证
  • Java如何实现Token登录验证
    这篇文章主要介绍“Java如何实现Token登录验证”,在日常操作中,相信很多人在Java如何实现Token登录验证问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”Java如何实现Token登录验证”的疑惑有所...
    99+
    2023-07-05
  • VUE实现token登录验证
    本文实例为大家分享了VUE实现token登录验证的具体代码,供大家参考,具体内容如下 实现这个登录功能的过程真是一波三折,中途出现了bug,整了两三天才解决了问题,心力交瘁,简直一个...
    99+
    2022-11-12
  • Vue项目中token验证登录(前端部分)
    本文实例为大家分享了Vue项目中token验证登录的具体代码,供大家参考,具体内容如下 1、前言 最近在做毕业设计,我是做后端的,前端并不是很懂,看vue这个框架看了近两个礼拜才有点...
    99+
    2022-11-12
  • Java登录功能实现token生成与验证
    一、token与cookie相比较的优势 1、支持跨域访问,将token置于请求头中,而cookie是不支持跨域访问的; 2、无状态化,服务端无需存储token,只...
    99+
    2022-11-12
  • vue实现token登录验证的完整实例
    目录token可用于登录验证和权限管理。登录页 -----Login.vue路由守卫 ----- router/index.js封装axios 添加请求拦截器 在每次请求之前进行的操...
    99+
    2022-11-13
  • Vue实现用户登录及token验证
    在前后端完全分离的情况下,Vue项目中实现token验证大致思路如下: 1、第一次登录的时候,前端调后端的登陆接口,发送用户名和密码 2、后端收到请求,验证用户名和密码,验证成功,就...
    99+
    2022-11-12
  • SpringBoot集成JWT实现Token登录验证
    目录 1.1 JWT是什么? 1.2 JWT主要使用场景 1.3 JWT请求流程 1.4 JWT结构 二,SpringBoot集成JWT具体实现过程 2.1添加相关依赖 2.2自定义跳出拦截器的注解 2.3自定义全局统一返回值方法,异常类...
    99+
    2023-09-06
    spring boot 后端 java
  • SpringBoot登录验证token拦截器的实现
    目录注解定义token生成与验证拦截器定义拦截器配置定义拦截器的方法执行类注解使用返回值-全局异常类定义各种测试不传token制造可行的假token伪造token测试拓展:从请求中获...
    99+
    2022-11-13
  • gogin+token(JWT)验证实现登陆验证
    1.准备 go get github.com/dgrijalva/jwt-go go get github.com/gin-gonic/gin  2.代码 package ...
    99+
    2022-11-12
  • SpringBoot实现扫码登录的项目实践
    目录一、首先咱们需要一张表二、角色都有哪些三、接口都需要哪些?四、步骤五、疯狂贴代码Spring Boot中操作WebSocket一、首先咱们需要一张表 这表是干啥的呢?就是记录一下...
    99+
    2022-11-13
  • SpringBoot登录验证token拦截器如何实现
    这篇文章主要讲解了“SpringBoot登录验证token拦截器如何实现”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“SpringBoot登录验证token拦截器如何实现”吧!用户访问接口验...
    99+
    2023-07-02
  • vue中如何实现登录注册及token验证
    这篇文章主要介绍了vue中如何实现登录注册及token验证,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让小编带着大家一起了解一下。具体实现代码如下:1. 利用rout...
    99+
    2022-10-19
  • Vue前端登录token信息验证功能实现
    用户在首次访问网站时,应在登录页面填写账号密码,前端携带用户信息向服务器请求。 1、服务器验证用户信息 验证失败:给前端响应数据 验证通过:对该用户创建token,并以响应数据返回给...
    99+
    2022-12-27
    Vue token验证 Vue前端token验证
  • 怎么用vue实现登录注册及token验证
    本篇内容主要讲解“怎么用vue实现登录注册及token验证”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“怎么用vue实现登录注册及token验证”吧!1. 利用router.beforeEach...
    99+
    2023-07-04
  • PHP实现JWT的Token登录认证
    1、JWT简介 JSON Web Token(缩写 JWT),是目前最流行的跨域认证解决方案。 session登录认证方案:用户从客户端传递用户名、密码等信息,服务端认证后将信息存储在session中,将session_id放到cookie...
    99+
    2017-03-29
    PHP实现Token登录认证 PHP Token认证 Token登录认证
  • go gin+token验证是怎么实现登陆验证
    本篇文章为大家展示了go gin+token验证是怎么实现登陆验证,内容简明扼要并且容易理解,绝对能使你眼前一亮,通过这篇文章的详细介绍希望你能有所收获。1.准备go get github.com/dgrija...
    99+
    2023-06-22
  • Python实现破解网站登录密码(带token验证)
    目录前言关键代码解释完整代码运行结果补充前言 上一篇暴力破解文章:一个简单的Python暴力破解网站登录密码脚本 测试靶机为Pikachu漏洞练习平台暴力破解模块下的 “...
    99+
    2022-11-13
  • ssm 使用token校验登录的实现
    背景 token的意思是“令牌”,是服务端生成的一串字符串,作为客户端进行请求的一个标识。 当用户第一次登录后,服务器生成一个token并将此token返回给客户端,以后客户端只需...
    99+
    2022-11-12
  • SSM项目使用拦截器实现登录验证功能
    目录登录接口实现拦截器类代码实现配置文件实现登录接口实现 public User queryUser(String UserName, String Password,HttpSe...
    99+
    2022-11-13
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作