SpringBoot中使用JWT令牌完成登录校验(hutool工具包)

一、JWT简单介绍

  JWT(JSON Web Token)是一种基于JSON的加密令牌,可以用作于前端向后端发起请求时的身份凭证。

JWT由三部分组成: 

(1)header :头部。指明了JWT使用的签名算法(例如HS256)和令牌类型(JWT),经过base64编码后形成令牌第一部分。

(2) payload :负载。简单来说该部分是可以放入一些不敏感的数据后经过base64编码得到,例如登录用户的id:

{
   "id" : 1
}

(3) signature : 签名。该部分保证了JWT令牌的安全性。这里我们需要自定义一个密钥(简单来说就是一个自定义的字符串)。由headerpayload经过base64编码后加上自定义密钥使用上文指定的HS256算法进行加密形成令牌的第三部分

所以最终生成的JWT令牌就会长这个样子 : header.payload.signature,  例如

eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VySWQiOjh9.0m8EK5x87XIDaEH7Yl7CbQi1Zj48-QoGIronj5YVCaM

这里就主要分享一下日常写springboot项目时如何去利用JWT完成简单的一个登录身份校验功能

二、依赖

  使用JWT首先要引入其依赖,因为我们使用的是hutool工具包中的JWT功能,所以这里我们引入的是hutool工具包的依赖

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

三、使用

(1)创建JWT

  要完成登录校验,我们首先要根据前端传来的登录参数查询我们的数据库看此次登录的用户是否存在,若存在我们就可以使用hutool包中的JWTUtil类的createToken() 创建JWT。

        HashMap<String, Object> map = new HashMap<>();
        map.put("userId", user.getId());
        String key = "wxxcxlogin";
        String token = JWTUtil.createToken(map, key.getBytes());
        System.out.println(token);

  createToken()方法有很多重载,这里我们选择使用的方法需要两个参数,

  1.   一个是用户自定的信息(payload)我们使用HashMap来传递,保存的是从数据库中查到的此次登录的用户ID。
  2.   另一个是上文提到的自定义的密钥。(ps:这里只是简单使用一下,一般来说应该把密钥定义在配置文件中)

  执行完方法后会自动生成一个token。

(2)使用JWT

  创建完后我们就要把JWT传递给前端,前端会将后端传递的JWT进行保存,并在之后需要登录身份验证的请求中都会在请求头中加上保存的JWT(也可封装一个共同的请求),以便后端能够从请求头中获取到JWT并加以校验,这里前端我们使用微信小程序作为示例:

 wx.setStorageSync('token', res.data.data.token)
 header: {
        'Content-Type': 'application/json', 
        'token': wx.getStorageSync('token'),
        ...header,
      },

这里只是简单示例一下,具体前端的逻辑还要小伙伴们根据自己的项目情况完成更改。

(3)后端校验JWT

  前端请求发出后,在后端中我们需要去创建一个拦截器来拦截请求并获取请求头中的JWT完成校验。

  具体代码逻辑如下:

@Component
@Slf4j
public class UserLoginInterceptor implements HandlerInterceptor {
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        // 1. 获取前端传来的token
        String token = request.getHeader("token");
        log.info("已获取到token:{}",token);

        // 2.判空
        if( token == null || token.equals("")){
            log.info("未登录,拒绝访问");
            return false;
        }

        // 3.验证并解析token , 获取数据
        String key = "wxxcxlogin";
        boolean result = JWTUtil.verify(token, key.getBytes());
        if( !result ){
            log.info("token错误,拒绝访问");
            return false;
        }
        JWT jwt = JWTUtil.parseToken(token);
        Integer userId = (Integer) jwt.getPayload("userId");


        // 4.判断
        if( userId == null || userId <= 0) {
            log.info("token错误,拒绝访问");
            return false;
        }

        // 5.token正确,保存用户id并放行
        Context.setCurrentId(userId);
        log.info("token校验成功,成功登录");
        return true;
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        // 清除掉ThreadLocal中的id
        Context.removeCurrentId();
    }
}

 这里使用ThreadLocal完成保存用户id的操作,这样方便后续使用

 具体代码逻辑如下:

public class Context {
    private static ThreadLocal<Integer> threadLocal = new ThreadLocal<>();

    public static Integer getCurrentId(){
        return  threadLocal.get();
    }

    public static void setCurrentId(Integer id) {
        threadLocal.set(id);
    }

    public static void removeCurrentId() {
        threadLocal.remove();
    }
}

  写完拦截器我们需要去配置类中注册拦截器

  具体代码逻辑如下:

@Configuration
public class MvcConfig extends WebMvcConfigurationSupport {
    @Autowired
    UserLoginInterceptor userLoginInterceptor;

    @Override
    protected void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(userLoginInterceptor)
                .addPathPatterns("/**")
                .excludePathPatterns("/user/**")
    }

}

  在配置类中我们可以用addPathPatternsexcludePathPatterns等方法来控制这个拦截器需要拦截和放行哪些请求。

(4)测试

     1.首先正常登录获取一个token

     2.其次可以用postman发起一个需要被拦截的请求并在其请求头中加入正确的token,看请求是否可以正常通过;

     3.然后修改token值并发起一个同样的请求,看请求是否被拦截。

结语:这样就使用hutool工具包完成了一个简易的基于JWT的登录身份校验功能

  • 15
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
对于Spring Boot应用程序记住密码和使用JWT令牌进行身份验证的场景,你可以按照以下步骤进行操作: 1. 添加依赖:在`pom.xml`文件添加Spring Security和JWT的依赖项。 ```xml <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-security</artifactId> </dependency> <dependency> <groupId>io.jsonwebtoken</groupId> <artifactId>jjwt</artifactId> <version>0.9.1</version> </dependency> ``` 2. 创建Spring Security配置类:创建一个类来扩展`WebSecurityConfigurerAdapter`,并覆盖`configure`方法。 ```java @Configuration @EnableWebSecurity public class SecurityConfig extends WebSecurityConfigurerAdapter { @Override protected void configure(HttpSecurity http) throws Exception { http.csrf().disable() .authorizeRequests() .antMatchers("/api/auth/**") .permitAll() .anyRequest() .authenticated(); } @Override public void configure(AuthenticationManagerBuilder auth) throws Exception { auth.userDetailsService(userDetailsService()) .passwordEncoder(passwordEncoder()); } @Bean @Override public UserDetailsService userDetailsService() { // 实现自定义的UserDetailsService接口来获取用户信息并进行身份验证 return new CustomUserDetailsService(); } @Bean public PasswordEncoder passwordEncoder() { // 使用BCryptPasswordEncoder来对密码进行加密和验证 return new BCryptPasswordEncoder(); } } ``` 3. 创建用户实体类:创建一个用户实体类,用于保存用户信息。 ```java @Entity @Table(name = "users") public class User implements UserDetails { // 实现UserDetails接口的方法 // 用户名、密码等其他属性 // getter和setter方法 } ``` 4. 创建自定义UserDetailsService:实现Spring Security的`UserDetailsService`接口,用于获取用户信息。 ```java @Service public class CustomUserDetailsService implements UserDetailsService { @Autowired private UserRepository userRepository; @Override public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException { User user = userRepository.findByUsername(username); if (user == null) { throw new UsernameNotFoundException("User not found with username: " + username); } return user; } } ``` 5. 创建JWT工具类:创建一个JWT工具类,用于生成和解析JWT令牌。 ```java @Component public class JwtTokenProvider { private static final String SECRET_KEY = "yourSecretKey"; private static final long EXPIRATION_TIME = 86400000; // 24小时 public String generateToken(Authentication authentication) { User user = (User) authentication.getPrincipal(); Date now = new Date(); Date expiryDate = new Date(now.getTime() + EXPIRATION_TIME); return Jwts.builder() .setSubject(user.getUsername()) .setIssuedAt(new Date()) .setExpiration(expiryDate) .signWith(SignatureAlgorithm.HS512, SECRET_KEY) .compact(); } public boolean validateToken(String token) { try { Jwts.parser().setSigningKey(SECRET_KEY).parseClaimsJws(token); return true; } catch (SignatureException ex) { System.out.println("Invalid JWT signature"); } catch (MalformedJwtException ex) { System.out.println("Invalid JWT token"); } catch (ExpiredJwtException ex) { System.out.println("Expired JWT token"); } catch (UnsupportedJwtException ex) { System.out.println("Unsupported JWT token"); } catch (IllegalArgumentException ex) {
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值