【圈友app】用户登录—校验登录、颁发token令牌

目录

校验登录

1.获取验证码

2.登录校验:分两部分,校验验证码和校验手机号。

        2.1 校验验证码

        2.2 校验手机号

        2.3 用户注册保存

        2.4 JWT生成token,颁发令牌

        2.5 构造返回值


校验登录

前端通过输入手机号进行验证登录,分两种状态:已注册/未注册

1.获取验证码

        输入手机号,点击获取登录验证码,后端通过RandomStringUtils工具类随机生成6为数字的验证码,并通过阿里云短信模板类SmsTemplate,调用该类对象的sendSms()方法,传入手机号和验证码参数,向手机发送短信。同时将验证码存入到redis中,通过调用RedisTemplate模板类的opsForValue().set()方法,设置键值。通过设置特定字符串+手机号的方式作为我们的key,来保证数据的一致性;验证码为值进行保存,同时还设置了redis中的验证码过期时间为5分钟。

    /**
     * 随机生成验证码
     * 发送短信验证码
     * 并保存在redis中
     * @param phone
     */
    public void sendMsg(String phone) {
        //1、随机生成6位数字
        String code = RandomStringUtils.randomNumeric(6);
//        String code = "123456";
        //2、调用template对象,发送手机短信
        template.sendSms(phone,code);
        //3、将验证码存入到redis
        redisTemplate.opsForValue().set("CHECK_CODE_"+phone,code, Duration.ofMinutes(5));
    }

2.登录校验:分两部分,校验验证码和校验手机号。

2.1 校验验证码

        首先是校验验证码是否保持一致,从redis中获取下发的验证码,通过调用RedisTemplate模板类的opsForValue().get()方法,输入特定字符串+传入的手机号作为key来获取对应的验证码值;比较redis中的验证码和用户输入的验证码码是否一致,不一致报错验证码错误或无效等字眼,反之,验证码一致则进行下一步校验手机号判断用户是否存在。

扫描二维码关注公众号,回复: 15017304 查看本文章

特别注意,这里验证码使用一次后要记得删除验证码,保证验证码一次性。通过调用RedisTemplate模板类delete()方法输入特定的key进行删除操作。


2.2 校验手机号

        通过使用Mybatis-plus里面的通用mapper来实现对数据库单表的CRUD操作。在Mapper的接口上继承BaseMapper的接口,其泛型为需要操作的数据库表对应的实体类。

        根据手机号查询对应的用户信息并返回,使用QueryWrapper封装查询条件,使用通用mapper的selectOne()方法传入条件对象并返回一个用户对象。对返回的用户进行判断,如果为null就是未注册,不为null说明已经注册过。

        定义一个布尔变量会返回给前端,false就是老用户,true就表示新用户。前端用来判断是新老用户,从而进行不同的页面跳转。


2.3 用户注册保存

如果用户为null,创建一个新用户并保存相关的信息,在进行设置保存密码时,通过DigestUtils.md5Hex("123456")进行加密;这里默认设置密码为123456。使用通用mapper的insert()方法保存用户,获取用户的id并返回,然后将id赋值给刚刚新创建的用户对象;这时设置布尔变量为true。


2.4 JWT生成token,颁发令牌

创建一个Map集合存入id和手机号码等用户的信息,并通过JwtUtils工具类的getToken()方法,传入map对用户信息构建生成token字符串;

通过实现JwtBuilder接口,调用Jwts.builder()返回一个新的JwtBuilder实例,它可以配置,然后用于创建JWT紧凑序列化字符串。

通过signWith()选择设置算法和加密方式,使用指定的算法和指定的密钥为构造JWT签名,生成JWS。

通过setExpiration()设置过期时间,addClaims()添加将所有给定的名称/值对添加到有效负载中的JSON Claims中。

通过compact()构建JWT并根据JWT compact Serialization规则将其序列化为紧凑的url安全字符串并返回。

最后将用户信息构建加密,返回一个token字符串,并对其进行保存返回。

特别注意:生成的token会保存在前端请求头中,保存在Authorization中,获取请求头中Authorization对应的值,就是在获取token用于身份校验。

JwtUtils工具类

import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import org.apache.commons.lang3.StringUtils;

import java.util.Date;
import java.util.Map;

public class JwtUtils {

    // TOKEN的有效期1小时(S)
    private static final int TOKEN_TIME_OUT = 3_600;

    // 加密KEY
    private static final String TOKEN_SECRET = "itcast";


    // 生成Token
    public static String getToken(Map params){
        long currentTime = System.currentTimeMillis();
        return Jwts.builder()
                .signWith(SignatureAlgorithm.HS512, TOKEN_SECRET) //加密方式
                .setExpiration(new Date(currentTime + TOKEN_TIME_OUT * 1000)) //过期时间戳
                .addClaims(params)
                .compact();
    }


    /**
     * 获取Token中的claims信息
     */
    public static Claims getClaims(String token) {
        return Jwts.parser()
                .setSigningKey(TOKEN_SECRET)
                .parseClaimsJws(token).getBody();
    }


    /**
     * 是否有效 true-有效,false-失效
     */
    public static boolean verifyToken(String token) {
      
        if(StringUtils.isEmpty(token)) {
            return false;
        }
        
        try {
            Claims claims = Jwts.parser()
                    .setSigningKey("itcast")
                    .parseClaimsJws(token)
                    .getBody();
        }catch (Exception e) {
            return false;
        }

		return true;
    }
}

 2.5 构造返回值

创建一个Map集合封装键值,根据前端要求添加token和布尔变量两个键值对,通过ResponseEntity封装实体并响应给前端。token用于身份校验,布尔变量用于判断新老用户。

如果是老用户,校验成功直接跳转到主页;如果是新用户,校验成功跳转页面进行信息完善页面。

校验登录方法— UserService

   /**
     * 验证登录
     * @param phone
     * @param code
     */
    public Map loginVerification(String phone, String code) {
        //1、从redis中获取下发的验证码
        String redisCode = redisTemplate.opsForValue().get("CHECK_CODE_" + phone);
        //2、对验证码进行校验(验证码是否存在,是否和输入的验证码一致)
        if(StringUtils.isEmpty(redisCode) || !redisCode.equals(code)) {
            //验证码无效
            throw new RuntimeException("验证码错误");
        }
        //3、删除redis中的验证码
        redisTemplate.delete("CHECK_CODE_" + phone);
        //4、通过手机号码查询用户
        User user = userApi.findByMobile(phone);
        boolean isNew = false;
        //5、如果用户不存在,创建用户保存到数据库中
        if(user == null) {
            user = new User();
            user.setMobile(phone);
            user.setPassword(DigestUtils.md5Hex("123456"));
            Long userId = userApi.save(user);
            user.setId(userId);
            isNew = true;
        }
        //6、通过JWT生成token(存入id和手机号码)
        Map tokenMap = new HashMap();
        tokenMap.put("id",user.getId());
        tokenMap.put("mobile",phone);
        String token = JwtUtils.getToken(tokenMap);
        //7、构造返回值
        Map retMap = new HashMap();
        retMap.put("token",token);
        retMap.put("isNew",isNew);

        return retMap;
    }

获取登录验证码及校验登录—— UserController

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

    @Resource
    private UserService userService;  
     
    /**
     * 获取登录验证码
     *   请求参数:phone (Map)
     *   响应:void
     * ResponseEntity
     */
    @PostMapping("/login")
    public ResponseEntity login(@RequestBody Map map){
        String phone =(String) map.get("phone");
        userService.sendMsg(phone);
        //return ResponseEntity.status(500).body("出错啦");
        return ResponseEntity.ok(null); //正常返回状态码200
    }

    /**
     * 检验登录
     */
    @PostMapping("/loginVerification")
    public ResponseEntity loginVerification(@RequestBody Map map) {
        //1、调用map集合获取请求参数
        String phone = (String) map.get("phone");
        String code = (String) map.get("verificationCode");
        //2、调用userService完成用户登录
        Map retMap = userService.loginVerification(phone,code);
        //3、构造返回
        return ResponseEntity.ok(retMap);
    }
}

猜你喜欢

转载自blog.csdn.net/zsy3757486/article/details/130026976