SpringBoot使用JWT实现登录验证的方法示例

以下是“SpringBoot使用JWT实现登录验证的方法示例”的完整攻略:

1. 什么是JWT?

JWT(JSON Web Token)是由JSON生成的令牌,通常用于身份验证和授权。它是一个开放标准(RFC 7519),通过在不同方之间安全地传输声明来作为JSON Web签名(JWS)或JSON Web加密(JWE)的方式。在Spring Boot中使用JWT可以达到一定的安全验证。

2. JWT的结构

一个JWT令牌由3个部分组成:

头部(Header)

头部包含了令牌的元数据,它包括了算法和类型等信息。例子:

{
  "alg": "HS256",
  "typ": "JWT"
}

负载(Payload)

负载包含了一些声明信息,比如用户ID,有效期时间等等。例子:

{
  "sub": "1234567890",
  "name": "John Doe",
  "iat": 1516239022
}

签名(Signature)

签名是对头部和负载进行签名的结果。根据头部中声明的算法和一个密钥,可以通过特殊的算法来生成一个签名。

3. Spring Boot使用JWT实现登录验证的方法示例

3.1 创建Spring Boot项目

首先,我们需要创建一个Spring Boot 项目。可以使用Spring Initializr 或是手动创建。

3.2 添加依赖

然后,我们需要添加依赖,包括 Spring Security 和JWT。在maven中添加以下依赖:

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

<dependency>
   <groupId>org.springframework.security</groupId>
   <artifactId>spring-security-test</artifactId>
   <scope>test</scope>
</dependency>

<dependency>
   <groupId>io.jsonwebtoken</groupId>
   <artifactId>jjwt</artifactId>
   <version>0.9.1</version>
</dependency>

3.3 实现UserDetailsService

接下来,我们需要实现一个Spring Security的UserDetailsService接口,用来根据用户名获取用户信息:

/**
 * Spring Security UserDetailsService 实现类
 * 用于获取用户信息
 */
@Service
public class UserDetailsServiceImpl implements UserDetailsService {

    @Autowired
    private UserService userService;

    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        User user = userService.findByUsername(username);
        if (user == null) {
            throw new UsernameNotFoundException(String.format("No user found with username '%s'.", username));
        } else {
            return JwtUserFactory.create(user);
        }
    }
}

3.4 创建JwtUtils

然后,我们需要创建一个JwtUtils类,用来生成和解析JWT令牌:

/**
 * JWT工具类,用来生成和解析JWT
 */
@Component
public class JwtUtils {

    @Value("${jwt.secret}")
    private String secret;

    @Value("${jwt.expires}")
    private long expiration;

    public String generateToken(UserDetails userDetails) {
        Map<String, Object> claims = new HashMap<>();
        claims.put(Claims.SUBJECT, userDetails.getUsername());
        claims.put(Claims.ISSUED_AT, new Date());
        return generateToken(claims);
    }

    public String generateToken(Map<String, Object> claims) {
        Date expirationDate = new Date(System.currentTimeMillis() + expiration * 1000);
        return Jwts.builder()
                .setClaims(claims)
                .setExpiration(expirationDate)
                .signWith(SignatureAlgorithm.HS256, secret)
                .compact();
    }

    public String getUsernameFromToken(String token) {
        return getClaimsFromToken(token).getSubject();
    }

    public Date getExpirationDateFromToken(String token) {
        return getClaimsFromToken(token).getExpiration();
    }

    public Claims getClaimsFromToken(String token) {
        return Jwts.parser()
                .setSigningKey(secret)
                .parseClaimsJws(token)
                .getBody();
    }

    public boolean validateToken(String token, UserDetails userDetails) {
        String username = getUsernameFromToken(token);
        return username.equals(userDetails.getUsername()) && !isTokenExpired(token);
    }

    public boolean isTokenExpired(String token) {
        Date expirationDate = getExpirationDateFromToken(token);
        return expirationDate.before(new Date());
    }
}

3.5 实现AuthenticationController

最后,我们需要实现一个AuthenticationController,用来处理登录认证,并生成JWT令牌:

@RestController
@RequestMapping("/auth")
public class AuthenticationController {

    @Autowired
    private AuthenticationManager authenticationManager;

    @Autowired
    private UserDetailsServiceImpl userDetailsService;

    @Autowired
    private JwtUtils jwtUtils;

    @PostMapping("/login")
    public ResponseEntity<?> login(@RequestBody LoginRequest loginRequest) throws AuthenticationException {

        // 验证用户和密码
        UserDetails userDetails = userDetailsService.loadUserByUsername(loginRequest.getUsername());
        UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(userDetails, loginRequest.getPassword());
        authenticationManager.authenticate(authenticationToken);

        // 生成JWT令牌
        String token = jwtUtils.generateToken(userDetails);
        return ResponseEntity.ok(new AuthenticationResponse(token));
    }
}

class LoginRequest {

    private String username;
    private String password;

    public String getUsername() {
        return username;
    }

    public String getPassword() {
        return password;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public void setPassword(String password) {
        this.password = password;
    }
}

class AuthenticationResponse {

    private final String token;

    public AuthenticationResponse(String token) {
        this.token = token;
    }

    public String getToken() {
        return token;
    }
}

到此处,整个登录认证的流程就完成了。

3.6 示例使用

3.6.1 登录

使用POST方式请求URL:"/auth/login",传递参数如下:

{
    "username":"admin",
    "password":"admin"
}

请求成功,将会得到类似如下的响应:

{
    "token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJhZG1pbiIsImlhdCI6MTYwNTQyMjQwNiwiZXhwIjoxNjA1NDIzMjA2fQ.om7Bvu_ikvUT6eUrJ67x9yvLsaJk3de-5Lb5mzyZ7fg"
}

3.6.2 调用受保护接口

修改我们的UserController:

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

    @GetMapping("/info")
    public String getInfo(@AuthenticationPrincipal JwtUserDetails auth) {
        return "username: " + auth.getUsername() + ", id: " + auth.getId();
    }
}

提供一个受保护的接口"/user/info",在方法参数中使用 "@AuthenticationPrincipal JwtUserDetails" 注解,即可获取当前登录用户的信息。

使用POST方式请求URL:"/auth/login"获取到的Token,构造一个新的Get请求Header: "Authorization",值为:"Bearer {token}",其中 {token} 为从服务器获取到的 Token 串,发送到URL:"/user/info"即可获取当前用户的信息。

这样,我们就实现了一个简单的使用JWT的Spring Boot登录认证流程。

4. 总结

以上就是实现基于SpringBoot + JWT的登录认证流程的详细攻略。JWT具有可扩展性、轻量级、安全性高等特点,在实际开发中也是比较常见的身份验证方式之一。通过以上的方式,你也可以轻松实现一个SpringBoot + JWT的登录认证功能。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:SpringBoot使用JWT实现登录验证的方法示例 - Python技术站

(0)
上一篇 2023年5月20日
下一篇 2023年5月20日

相关文章

  • Android 解析JSON对象及实例说明

    Android 解析JSON对象及实例说明 什么是JSON? JSON(JavaScript Object Notation)是一种轻量级的数据交换格式,它基于JavaScript语言的一个子集,因此容易被人阅读和编写,同时也易于机器解析和生成。在Web应用程序中,JSON通常用来传递从服务器到客户端的数据。 Android中使用JSON Android中提…

    Java 2023年6月15日
    00
  • SpringBoot使用validation做参数校验说明

    下面是Spring Boot使用Validation做参数校验的攻略: 什么是Validation Validation是一种Java Bean Validation规范的实现,它提供了一种声明式验证的方式,可以在不依赖业务逻辑的情况下对请求参数进行校验,从而避免了代码重复和漏写校验的问题。 如何使用Validation 第一步:添加Validation依赖…

    Java 2023年5月20日
    00
  • Java NegativeArraySizeException异常解决方案

    我将为您讲解解决“Java NegativeArraySizeException异常”的完整攻略。 什么是NegativeArraySizeException异常? 首先,我们需要了解一下NegativeArraySizeException异常。它是Java中的一种运行时异常,当我们使用负数作为数组大小时,就会抛出这个异常。 解决方案 要解决Negative…

    Java 2023年5月27日
    00
  • 数据库其它

    关于“数据库其它”的攻略,我可以向你分享以下内容: 什么是“数据库其他” 在数据库领域中,通常我们在日常工作中会遇到常见的数据库如MySQL、Oracle、SQL Server等,但是还存在一些相对冷门但是非常有用的数据库,这些数据库就是“数据库其他”。这些数据库通常也有独特的使用场景和应用需求,有一定的价值。下面是一些常见的“数据库其他”: MongoDB…

    Java 2023年5月19日
    00
  • 使用Java实现DNS域名解析的简单示例

    下面我将为您详细讲解“使用Java实现DNS域名解析的简单示例”的完整攻略。 什么是DNS? DNS(Domain Name System)是一种将域名转换为IP地址的互联网服务。DNS将人类可读的域名转换为机器可读的IP地址。例如,www.baidu.com域名会被DNS服务器解析为IP地址,例如:220.181.110.6。 Java实现DNS域名解析 …

    Java 2023年5月19日
    00
  • Java异常处理的机制是什么?

    Java异常处理机制是一种处理程序错误的方式。在Java程序运行时,如果程序出现错误(如除0、数组下标越界等),程序会抛出一个异常对象。此时,Java会尝试查找能够处理该异常的异常处理程序,若找到则执行该处理程序,若没有找到则程序终止并输出堆栈跟踪信息。 Java异常处理机制主要分为异常抛出、异常捕获和异常处理三个部分。 1.异常抛出 在Java中,异常是以…

    Java 2023年4月27日
    00
  • java实现页面置换算法

    Java 实现页面置换算法的完整攻略分为以下几个步骤: 1. 简述页面置换算法 页面置换算法是指当一个进程需要访问的页面不在物理内存中时,需要替换掉内存中的某一页,为该页面腾出空间。页面置换算法的主要目标是选择正确的页面替换策略,以最小化缺页次数,并提高操作系统的性能。 2. 确定实现页面置换算法的数据结构 常用的数据结构包括链表、数组和哈希表。在本攻略中,…

    Java 2023年5月18日
    00
  • Java用递归方法解决汉诺塔问题详解

    Java用递归方法解决汉诺塔问题详解 问题描述 汉诺塔问题的经典描述是:在有三根柱子的情况下,有三个大小不同的盘子从下往上按从大到小的顺序放在柱子A上,要将这三个盘子移动到柱子C上,要求每次只能移动一个盘子,且大盘子不能放在小盘子上面。 解题思路 汉诺塔问题是递归问题的典型,使用递归可以比较简单地解决该问题。 我们可以将解决汉诺塔问题的方法抽象为三个步骤: …

    Java 2023年5月19日
    00
合作推广
合作推广
分享本页
返回顶部