第三⼗⼆章 项⽬实战之⽤户注册登录模块和JWT登录解决⽅案


1集 ⼩滴课堂实战之⽤户注册功能开发和MD5加密⼯具类封装

简介:⽤户注册功能接⼝开发

  • 注册接⼝开发 
//增加唯⼀索引
CREATE TABLE `user` (
 `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
 `name` varchar(128) DEFAULT NULL COMMENT '昵称',
 `pwd` varchar(124) DEFAULT NULL COMMENT '密码',
 `head_img` varchar(524) DEFAULT NULL COMMENT '头像',
 `phone` varchar(64) DEFAULT '' COMMENT '⼿机号',
 `create_time` datetime DEFAULT NULL COMMENT '创建时间',
 PRIMARY KEY (`id`),
 UNIQUE KEY `phone` (`phone`)
) ENGINE=InnoDB AUTO_INCREMENT=8 DEFAULT CHARSET=utf8;

MD5 加密⼯具类封装(不⽤死记,不常⽤的⽅法,直接拷⻉使⽤就⾏,基本是写⼀次,其他项⽬
直接拷⻉)
public class MD5Util {
    public static String MD5(String data) {
        try {
            java.security.MessageDigest md =
                    MessageDigest.getInstance("MD5");
            byte[] array = md.digest(data.getBytes("UTF-8"));
            StringBuilder sb = new StringBuilder();
            for (byte item : array) {
                sb.append(Integer.toHexString((item & 0xFF) |
                        0x100).substring(1, 3));
            }
            return sb.toString().toUpperCase();
        } catch (Exception exception) {
        }
        return null;
    }



}
public class Headutil {
    //随机头像生成
    public static final String [] headImg = {
            "https://xd-video-pc-img.oss-cnbeijing.aliyuncs.com/xdclass_pro/default/head_img/12.jpeg",
            "https://xd-video-pc-img.oss-cnbeijing.aliyuncs.com/xdclass_pro/default/head_img/11.jpeg",
            "https://xd-video-pc-img.oss-cnbeijing.aliyuncs.com/xdclass_pro/default/head_img/13.jpeg",
            "https://xd-video-pc-img.oss-cnbeijing.aliyuncs.com/xdclass_pro/default/head_img/14.jpeg",
            "https://xd-video-pc-img.oss-cnbeijing.aliyuncs.com/xdclass_pro/default/head_img/15.jpeg"
    };
}

UserController:

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

    /**
     * 注册
     */
    @Autowired
    private UserService userService;
    @PostMapping("register")
    public JsonData RegisterUser(@RequestBody Map<String,String> userInfo){
        int rows = userService.save(userInfo);
      return rows ==1 ? JsonData.JsonDataBuild(""):JsonData.JsonDataError("",-6,"注册失败,请重试");
    }
}

UserServiceImpl:

@Service
public class UserServiceImpl implements UserService {
    @Autowired
    private UserMapper userMapper;
    @Override
    public int save(Map<String,String> userInfo) {
        User user = parseToUser(userInfo);
        if (user!=null){
            return  userMapper.save(user);
        }else { //注册失败
            return -1;
        }

    }

    private User parseToUser(Map<String, String> userInfo) {
        if (userInfo.containsKey("phone") && userInfo.containsKey("name") && userInfo.containsKey("pwd")){
            User user = new User();
            user.setPhone(userInfo.get("phone"));
            user.setName(userInfo.get("name"));
            user.setCreateTime(new Date());
            user.setHeadImg(getRandomImg());
            //MD5加密操作
            String MD5pwd = MD5Util.MD5(userInfo.get("pwd"));
            user.setPwd(MD5pwd);
            return user;
        }
        return null;
    }
    private String getRandomImg(){
        String[] headImgs = Headutil.headImg;
        int size = headImgs.length;
        //随机数
        Random random = new Random();
        int randomInt = random.nextInt(size);
        return headImgs[randomInt];

    }

}

Mapper:

<insert id="save" parameterType="User">
        insert into user(name,pwd,head_img,phone,create_time)
        value(#{name,jdbcType=VARCHAR},#{pwd,jdbcType=VARCHAR},#{headImg,jdbcType=VARCHAR}
        ,#{phone,jdbcType=VARCHAR},#{createTime,jdbcType=TIMESTAMP})
    </insert>

2集 常⻅的互联⽹项⽬中 单机和分布式应⽤的登录校验解决⽅案

简介:讲解单机和分布式应⽤下登录校验, session 共享,分布式缓存使⽤
  • 单机tomcat应⽤登录检验
    • sesssion保存在浏览器和应⽤服务器会话之间
    • ⽤户登录成功,服务端会保存⼀个 session ,当然客户端有⼀个 sessionId
    • 客户端会把 sessionId 保存在 cookie 中,每次请求都会携带这个 sessionId
  • 分布式应⽤中session共享 
    • 真实的应⽤不可能单节点部署,所以就有个多节点登录 session 共享的问题需要解决
    • tomcat ⽀持 session 共享,但是有⼴播⻛暴;⽤户量⼤的时候,占⽤资源就严重,不推荐

      使⽤redis存储token:

      • 服务端使⽤UUID⽣成随机64位或者128token,放⼊redis中,然后返回给客户端并存储在cookie
      • ⽤户每次访问都携带此 token ,服务端去 redis 中校验是否有此⽤户即可

      3集 分布式应⽤下登录检验解决⽅案 JWT讲解 

                简介:分布式应⽤的登录检验解决⽅案 JWT讲解 json wen token 

  •  什么是JWT
    • JWT 是⼀个开放标准,它定义了⼀种⽤于简洁,⾃包含的⽤于通信双⽅之间以 JSON 对象的形式安全传递信息的⽅法。 可以使⽤ HMAC 算法或者是 RSA 的公钥密钥对进⾏签名
    • 简单来说 : 就是通过⼀定规范来⽣成 token ,然后可以通过解密算法逆向解密 token ,这样就 可以获取⽤户信息
  • 优点
    • ⽣产的token可以包含基本信息,⽐如id、⽤户昵称、头像等信息,避免再次查库
    • 存储在客户端,不占⽤服务端的内存资源
  • 缺点
    • token是经过base64编码,所以可以解码,因此token加密前的对象不应该包含敏感信 ​​​​​息,如⽤户权限,密码等
    •  如果没有服务端存储,则不能做登录失效处理,除⾮服务端改秘钥
  • JWT 格式组成 头部、负载、签名
    • header+payload+signature
      • 头部:主要是描述签名算法
      • 负载:主要描述是加密对象的信息,如⽤户的 id 等,也可以加些规范⾥⾯的东⻄,如 iss签发者,exp 过期时间, sub ⾯向的⽤户
        签名:主要是把前⾯两部分进⾏加密,防⽌别⼈拿到 token 进⾏ base 解密后篡改 token
  • 关于jwt客户端存储 
    • 可以存储在 cookie localstorage sessionStorage ⾥⾯

4集 登录校验Json Web Token实战之封装通⽤⽅法 

 讲解:引⼊相关依赖并开发JWT⼯具类, 开发⽣产token和校验token的办法

  •  加⼊相关依赖
<!-- JWT 相关 -->
<dependency>
        <groupId>io.jsonwebtoken</groupId>
        <artifactId>jjwt</artifactId>
        <version>0.7.0</version>
</dependency>

 

  • 封装⽣产token⽅法 和解密token方法
public class JWTUtils {

    /**
     * 设置过期时间,一周
     */
    private static final long EXPIRE = 6000 * 60 * 24 * 7;
    /**
     * 加密秘钥
     */
    private static final String SECRET = "xjclass.net188";

    /**
     * 令牌前缀
     */
    private static final String TOKEN_PREFIX = "xjclass";
    /**
     * subject
     */
    private static final  String SUBJECT = "xjclass";


    /**
     * 根据用户信息,生成令牌
     * @param user
     * @return
     */
    public static String geneJsonWebToken(User user){
        String token = Jwts.builder().setSubject(SUBJECT)
                .claim("head_img",user.getHeadImg())
                .claim("name",user.getName())
                .claim("id",user.getId())
                .setIssuedAt(new Date())
                .setExpiration(new Date(System.currentTimeMillis() + EXPIRE))
                .signWith(SignatureAlgorithm.HS256,SECRET)
                .compact();
        token = TOKEN_PREFIX + token;
        return token;
    }

    /**
     * 身份校验
     * @param token
     * @return
     */
    public static Claims CheckJWT(String token){
        try{
            final Claims claims = Jwts.parser().setSigningKey(SECRET)
                    .parseClaimsJws(token.replace(TOKEN_PREFIX,"")).getBody();
            return claims;

        }catch (Exception e){ //秘钥出错或者EXPIRE过期会解密失败
            return null;
        }


    }

}

5集 ⼩滴课堂实战之登录模块开发整合Json Web Token

简介:开发登录模块功能,并整合JSON Web Token 

  • 修改domain model
    • 增加 entity request (LoginRequest中有手机号和密码,相当于迭代,只拿出我们请求的属性) 
    • 记得改 application.properties 配置⽂件扫描路径 !!!!
       

UserController:

 @PostMapping("login")
    public JsonData Login(@RequestBody LoginRequest loginRequest ){
        String  token = userService.findByPhoneAndPwd(loginRequest.getPhone(),loginRequest.getPwd());
       return  token == null ?JsonData.JsonDataError("",-100,"登录失败,账号或者密码错误") :  JsonData.JsonDataBuild(token);


    }

 UserServiceImpl:

 @Override
    public String findByPhoneAndPwd(String phone, String pwd) {
        //给pwd加密
       User  user =  userMapper.findByPhoneAndPwd(phone,MD5Util.MD5(pwd));
       String token = null;
        if (user == null){
            return null;
        }else{
            //生成token
            token = JWTUtils.geneJsonWebToken(user);
        }
       return token;
    }

mapper文件:


    <select id="findByPhoneAndPwd" resultType="User">
        select * from user where phone = #{phone,jdbcType = VARCHAR} and pwd = #{pwd,jdbcType = VARCHAR}
    </select>

运行结果返回JSON数据:

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值