SpringBoot集成JWT

1.导入依赖

    <!--JWT-->
    <dependency>
        <groupId>com.auth0</groupId>
        <artifactId>java-jwt</artifactId>
        <version>3.10.3</version>
    </dependency>

2.创建TokenUtils

​import cn.hutool.core.util.StrUtil;
import com.auth0.jwt.JWT;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.interfaces.DecodedJWT;
import com.auth0.jwt.interfaces.JWTVerifier;
import com.ethan.exam_ms.entity.User;
import com.ethan.exam_ms.exception.ServiceException;
​
import java.util.Calendar;
import java.util.Date;
​
public class TokenUtils {
    //密钥
    public static final String SECRET = "areyoucrazy?pojie?bukenengde?";
    //过期时间:秒
    public static final int EXPIRE = 30;
    public static String getToken(String id,String username){
        Calendar nowTime = Calendar.getInstance();
        //过期时间
        nowTime.add(Calendar.SECOND, EXPIRE);
        Date expireDate = nowTime.getTime();
        String token = JWT.create()
                //这是在设置第二部分信息,不要设置密码之类的,因为这些信息可以通过浏览器获取
                //用户id
                .withClaim("id", id)
                //用户名
                .withClaim("username",username)
                //创建token的时间
                .withIssuedAt(new Date())//签名时间
                //设置token的过期时间
                .withExpiresAt(expireDate)//过期时间
                //设置第一部分
                .sign(Algorithm.HMAC256(SECRET));//签名
        return token;
​
    }
    /**
     * 验证token合法性 成功返回token
     */
    public static DecodedJWT verify(String token) throws ServiceException {
        if(StrUtil.isBlank(token)){
            throw new ServiceException("token不能为空");
        }
        JWTVerifier build = JWT.require(Algorithm.HMAC256(SECRET)).build();
        return build.verify(token);
    }
​
​
}

3.登录拦截器

(1)没有统一返回类,用map封装

import cn.hutool.core.util.StrUtil;
import com.auth0.jwt.exceptions.AlgorithmMismatchException;
import com.auth0.jwt.exceptions.SignatureVerificationException;
import com.auth0.jwt.exceptions.TokenExpiredException;
import com.ethan.exam_ms.exception.ServiceException;
import com.ethan.exam_ms.utils.TokenUtils;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.HashMap;
import java.util.Map;
​
​
@Slf4j
@Component
public class LoginInterceptor implements HandlerInterceptor {
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        Map<String,Object> map=new HashMap<>();
        //从请求中获得token
        String token = request.getHeader("token");
        if(!(handler instanceof HandlerMethod)){
            return true;
        }
​
        if(StrUtil.isEmpty(token)){
            throw new ServiceException("NOTLOGIN");
        }
        try {
            TokenUtils.verify(token);
            return true;
        } catch (SignatureVerificationException e) {
            map.put("msg","无效签名! 错误 ->");
​
        } catch (TokenExpiredException e) {
            map.put("msg","token过期! 错误 ->");
​
        } catch (AlgorithmMismatchException e) {
            map.put("msg","token算法不一致! 错误 ->");
​
​
        } catch (Exception e) {
            map.put("msg","token无效! 错误 ->");
​
​
        }
        map.put("state",false);
        
        //设置响应
        String json=new ObjectMapper().writeValueAsString(map);
        response.setContentType("application/json;charset=UTF-8");
        response.getWriter().println(json);
        return false;
​
​
​
​
    }
​
​
}

(2)有统一返回类,用R

import cn.hutool.core.util.StrUtil;
import com.auth0.jwt.exceptions.AlgorithmMismatchException;
import com.auth0.jwt.exceptions.SignatureVerificationException;
import com.auth0.jwt.exceptions.TokenExpiredException;
import com.ethan.exam_ms.common.R;
import com.ethan.exam_ms.exception.ServiceException;
import com.ethan.exam_ms.utils.TokenUtils;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;
​
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.HashMap;
import java.util.Map;
​
​
@Slf4j
@Component
public class LoginInterceptor implements HandlerInterceptor {
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        String erroMsg=null;
        //从请求中获得token
        String token = request.getHeader("token");
        if(!(handler instanceof HandlerMethod)){
            return true;
        }
​
        if(StrUtil.isEmpty(token)){
            throw new ServiceException("NOTLOGIN");
        }
        try {
            TokenUtils.verify(token);
            return true;
        } catch (SignatureVerificationException e) {
​
             erroMsg="无效签名! 错误 ";
​
        } catch (TokenExpiredException e) {
            erroMsg="token过期! 错误 ";
​
        } catch (AlgorithmMismatchException e) {
            erroMsg="token算法不一致! 错误 ";
​
​
        } catch (Exception e) {
            erroMsg="token无效! 错误";
​
        }
​
        String json=new ObjectMapper().writeValueAsString(R.error(erroMsg));
        response.setContentType("application/json;charset=UTF-8");
        response.getWriter().println(json);
        return false;
​
​
    }
​
}
 

4.配置拦截器

import com.ethan.exam_ms.common.JacksonObjectMapper;
import com.ethan.exam_ms.interceptor.LoginInterceptor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
​
import javax.annotation.Resource;
import java.util.List;
​
@Slf4j
@Configuration
public class WebMvcConfig implements WebMvcConfigurer {
​
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
​
        registry.addInterceptor(loginInterceptor)
                .addPathPatterns("/**")
            //排除不需要拦截的请求
                .excludePathPatterns(
                        "/manager/login",
                        "/user/login",
                        "/login",
                        "/manager/logout"
                );
    }
​
}

5.Controller里使用

UserController

/**
 * 用户登录
 * @param loginDto
 * @return
 */
@PostMapping("login")
public R<LoginDto> toLogin(HttpServletRequest request, @RequestBody LoginDto loginDto){
    log.info("登录名:{},登录密码:{}",loginDto.getUsername(),loginDto.getPassword());
​
    String username = loginDto.getUsername();
    String password = loginDto.getPassword();
    //1.判断输入值是否为空
    if(StringUtils.isBlank(username)||StringUtils.isBlank(password)){
        return R.error("用户名或密码不可为空");
    }
    LoginDto login = userService.login(loginDto);
    return R.success(login);
 
}

UserServiceImpl

import cn.hutool.core.bean.BeanUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ethan.exam_ms.dto.LoginDto;
import com.ethan.exam_ms.entity.Manager;
import com.ethan.exam_ms.entity.User;
import com.ethan.exam_ms.exception.ServiceException;
import com.ethan.exam_ms.mapper.UserMapper;
import com.ethan.exam_ms.service.UserService;
import com.ethan.exam_ms.utils.TokenUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.util.DigestUtils;
@Slf4j
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {
    public LoginDto login(LoginDto loginDto) {
​
        String password = loginDto.getPassword();
        //1.对密码进行md5加密
        password= DigestUtils.md5DigestAsHex(password.getBytes());
        log.info("加密后的密码:{}",password);
        User one = getUserInfo(loginDto);
        if (one != null) {
            BeanUtil.copyProperties(one, loginDto, true);
​
            // 设置token
            String token = TokenUtils.getToken(one.getId().toString(),one.getNickname());
            loginDto.setToken(token);
​
            return loginDto;
        } else {
            throw new ServiceException("用户名或密码错误");
        }
​
    }
    public User getUserInfo(LoginDto loginDto) {
        LambdaQueryWrapper<User> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(User::getNickname, loginDto.getUsername());
        queryWrapper.eq(User::getPassword, DigestUtils.md5DigestAsHex(loginDto.getPassword().getBytes()));
        User one;
        try {
            one = getOne(queryWrapper); // 从数据库查询用户信息
        } catch (Exception e) {
            //这个地方需要写个全局异常处理类,自定义一个ServiceException方法来处理异常
            throw new ServiceException("系统错误");
        }
        return one;
    }
}

其他UserService,mapper文件使用了mybatis-plus较为简单省略

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Ethan_Zhuo

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值