第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位或者128位token,放⼊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数据: