自学内容网 自学内容网

记一次实战项目所学(JWT篇)

记一次实战项目所学(JWT篇)

5. 登录验证功能

先获取公钥准备将前端输入的进行加密

    //获得公钥
    @GetMapping("/rsa-pks")
    public JsonResponse<String> getRsaPublicKey(){
        String publicKeyStr = RSAUtil.getPublicKeyStr();
        return  new JsonResponse<>(publicKeyStr);
    }
新建(注册)一个user

(controller层)

      //新建一个用户
    @PostMapping("/users")          //@RequestBody 把User 封装成json数据返回
    public JsonResponse<String>addUser(@RequestBody User user){
        userService.addUser(user);
        return  JsonResponse.success();
    }

​ (Service层)

@Service
public class UserService {
    @Autowired
    private UserDao userDao;

    public void addUser(User user) {
        String phone = user.getPhone();
        if (StringUtils.isNullOrEmpty(phone)) {
            throw new ConditionException("手机号不能为空!");
        }
        User dbUser = this.getUserByPhone(phone);
        if (dbUser != null) {
            throw new ConditionException("该手机号已经被注册");

        }
        //加密需要
        Date now = new Date();
        //md5需要加密
        String salt = String.valueOf(now.getTime());
        String password = user.getPassword();
        String rawPassword;

        try {
            rawPassword = RSAUtil.decrypt(password);//该密码已经通过前端获取的公钥加密
        } catch (Exception e) {
            throw new ConditionException("解密失败");

        }
        String md5Password = MD5Util.sign(rawPassword, salt, "UTF-8");
        user.setSalt(salt);
        user.setPassword(md5Password);
        user.setCreateTime(now);
        userDao.addUser(user);

        //添加用户信息(这里有两张表user和userinfo )
        UserInfo userInfo = new UserInfo();
        userInfo.setUserId(user.getId());
        userInfo.setNick(UserConstant.DEFAULT_NICK);
        userInfo.setBirth(UserConstant.DEFAULT_BIRTH);
        userInfo.setGender(UserConstant.GENDER_FEMALE);
        userInfo.setCreateTime(now);
        userDao.addUserInfo(userInfo);


    }

    public User getUserByPhone(String phone) {
        return userDao.getUserByPhone(phone);
    }

dao层为数据操作不再贴代码啦

用户登录

controller

  //用户登录
    @PostMapping("/user-tokens")
    public  JsonResponse<String> login(@RequestBody User user) throws Exception{
        String token=userService.login(user);
        return new JsonResponse<>(token);
    }

service

public String login(User user) throws Exception {
        String phone = user.getPhone();
        if (StringUtils.isNullOrEmpty(phone)) {
            throw new ConditionException("手机号不能为空!");}
            User dbUser = this.getUserByPhone(phone);
            if (dbUser == null) {
                throw new ConditionException("当前用户不存在");

            }
            String password = user.getPassword();
            String rowpassword;
            try {
                rowpassword = RSAUtil.decrypt(password);

            } catch (Exception e) {
                throw new ConditionException("密码解密失败");

            }
            String salt = dbUser.getSalt();
            String md5Password = MD5Util.sign(rowpassword, salt, "UTF-8");
            if (!md5Password.equals(dbUser.getPassword())) {
                throw new ConditionException("密码错误!");

            }

        return TokenUtil.generateToken(dbUser.getId());
    }
前端加密不安全,数据库存入的密码应该是不可逆的,每次认证时候前端传入密码加密后跟后端数据库里密码比对,如果一样密码正确,如果不一样密码不正确,前端加密后传输是怕传输过程被拦截获取到明文密码

因为id是唯一的所以id可以作为token

5.5 基于JWT的用户的token验证

在这里插入图片描述
1710307369465)

在这里插入图片描述

依赖

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

util.token

import com.auth0.jwt.JWT;
import com.auth0.jwt.JWTVerifier;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.exceptions.TokenExpiredException;
import com.auth0.jwt.interfaces.DecodedJWT;
import com.imooc.bilibili.domain.except.ConditionException;

import java.util.Calendar;
import java.util.Date;

public class TokenUtil {
    private  static  final  String ISSUER="签发者"; //签发者是谁,随意填
    public static String generateToken(Long userId) throws Exception{
        Algorithm algorithm = Algorithm.RSA256(RSAUtil.getPublicKey(),RSAUtil.getPrivateKey());
        Calendar calendar =Calendar.getInstance(); //用于实现过期时间
        calendar.setTime(new Date());
        calendar.add(Calendar.SECOND,30); //30s过期
        return JWT.create().withKeyId(String.valueOf(userId))
                .withIssuer(ISSUER)
                .withExpiresAt(calendar.getTime())
                .sign(algorithm);
    }
//解密
    public  static  Long verifyToken(String token) {
        try{
            Algorithm algorithm =Algorithm.RSA256(RSAUtil.getPublicKey(),RSAUtil.getPrivateKey());
            JWTVerifier verifier =JWT.require(algorithm).build();
            DecodedJWT jwt= verifier.verify(token);
            String keyId = jwt.getKeyId();
            return  Long.valueOf(keyId);
        }catch (TokenExpiredException e){
            throw  new ConditionException("555","token过期!");

        }catch (Exception e){
            throw  new ConditionException("非法用户token");
        }



    }
}

需要一个通用方法,获取token里的userid(一般放在请求头里)

import com.imooc.bilibili.domain.except.ConditionException;
import com.imooc.bilibili.service.Util.TokenUtil;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.ServletRequest;

@Component
public class UserSupport {
    public  Long getCurrentUserId(){
        //抓取请求上下文,获取token(在请求头中)+
        ServletRequestAttributes requestAttributes =(ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        String token =requestAttributes.getRequest().getHeader("token");
        Long userId= TokenUtil.verifyToken(token);
        if(userId<0){
            throw  new ConditionException("非法用户!");

        }
        return  userId;

    }
}


原文地址:https://blog.csdn.net/qq_43660290/article/details/136677347

免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!