Commit c347358e authored by Ma's avatar Ma Committed by linlinjava
Browse files

SQL用户表增加字段,小程序后端登录验证方式采用JWT (#167)

parent 20ea711a
......@@ -735,6 +735,7 @@ CREATE TABLE `litemall_user` (
`mobile` varchar(20) NOT NULL DEFAULT '' COMMENT '用户手机号码',
`avatar` varchar(255) NOT NULL DEFAULT '' COMMENT '用户头像图片',
`weixin_openid` varchar(63) NOT NULL DEFAULT '' COMMENT '微信登录openid',
`session_key` varchar(100) NOT NULL DEFAULT '' COMMENT '微信登录会话KEY',
`status` tinyint(3) NOT NULL DEFAULT '0' COMMENT '0 可用, 1 禁用, 2 注销',
`add_time` datetime DEFAULT NULL COMMENT '创建时间',
`update_time` datetime DEFAULT NULL COMMENT '更新时间',
......
......@@ -132,6 +132,15 @@ public class LitemallUser {
*/
private String weixinOpenid;
/**
*
* This field was generated by MyBatis Generator.
* This field corresponds to the database column litemall_user.session_key
*
* @mbg.generated
*/
private String sessionKey;
/**
*
* This field was generated by MyBatis Generator.
......@@ -456,6 +465,30 @@ public class LitemallUser {
this.weixinOpenid = weixinOpenid;
}
/**
* This method was generated by MyBatis Generator.
* This method returns the value of the database column litemall_user.session_key
*
* @return the value of litemall_user.session_key
*
* @mbg.generated
*/
public String getSessionKey() {
return sessionKey;
}
/**
* This method was generated by MyBatis Generator.
* This method sets the value of the database column litemall_user.session_key
*
* @param sessionKey the value for litemall_user.session_key
*
* @mbg.generated
*/
public void setSessionKey(String sessionKey) {
this.sessionKey = sessionKey;
}
/**
* This method was generated by MyBatis Generator.
* This method returns the value of the database column litemall_user.status
......@@ -576,6 +609,7 @@ public class LitemallUser {
sb.append(", mobile=").append(mobile);
sb.append(", avatar=").append(avatar);
sb.append(", weixinOpenid=").append(weixinOpenid);
sb.append(", sessionKey=").append(sessionKey);
sb.append(", status=").append(status);
sb.append(", addTime=").append(addTime);
sb.append(", updateTime=").append(updateTime);
......@@ -614,6 +648,7 @@ public class LitemallUser {
&& (this.getMobile() == null ? other.getMobile() == null : this.getMobile().equals(other.getMobile()))
&& (this.getAvatar() == null ? other.getAvatar() == null : this.getAvatar().equals(other.getAvatar()))
&& (this.getWeixinOpenid() == null ? other.getWeixinOpenid() == null : this.getWeixinOpenid().equals(other.getWeixinOpenid()))
&& (this.getSessionKey() == null ? other.getSessionKey() == null : this.getSessionKey().equals(other.getSessionKey()))
&& (this.getStatus() == null ? other.getStatus() == null : this.getStatus().equals(other.getStatus()))
&& (this.getAddTime() == null ? other.getAddTime() == null : this.getAddTime().equals(other.getAddTime()))
&& (this.getUpdateTime() == null ? other.getUpdateTime() == null : this.getUpdateTime().equals(other.getUpdateTime()))
......@@ -642,6 +677,7 @@ public class LitemallUser {
result = prime * result + ((getMobile() == null) ? 0 : getMobile().hashCode());
result = prime * result + ((getAvatar() == null) ? 0 : getAvatar().hashCode());
result = prime * result + ((getWeixinOpenid() == null) ? 0 : getWeixinOpenid().hashCode());
result = prime * result + ((getSessionKey() == null) ? 0 : getSessionKey().hashCode());
result = prime * result + ((getStatus() == null) ? 0 : getStatus().hashCode());
result = prime * result + ((getAddTime() == null) ? 0 : getAddTime().hashCode());
result = prime * result + ((getUpdateTime() == null) ? 0 : getUpdateTime().hashCode());
......@@ -680,6 +716,7 @@ public class LitemallUser {
mobile("mobile", "mobile", "VARCHAR", false),
avatar("avatar", "avatar", "VARCHAR", false),
weixinOpenid("weixin_openid", "weixinOpenid", "VARCHAR", false),
sessionKey("session_key", "sessionKey", "VARCHAR", false),
status("status", "status", "TINYINT", true),
addTime("add_time", "addTime", "TIMESTAMP", false),
updateTime("update_time", "updateTime", "TIMESTAMP", false),
......
......@@ -1893,6 +1893,148 @@ public class LitemallUserExample {
return (Criteria) this;
}
public Criteria andSessionKeyIsNull() {
addCriterion("session_key is null");
return (Criteria) this;
}
public Criteria andSessionKeyIsNotNull() {
addCriterion("session_key is not null");
return (Criteria) this;
}
public Criteria andSessionKeyEqualTo(String value) {
addCriterion("session_key =", value, "sessionKey");
return (Criteria) this;
}
/**
* This method was generated by MyBatis Generator.
* This method corresponds to the database table litemall_user
*
* @mbg.generated
* @project https://github.com/itfsw/mybatis-generator-plugin
*/
public Criteria andSessionKeyEqualToColumn(LitemallUser.Column column) {
addCriterion(new StringBuilder("session_key = ").append(column.getEscapedColumnName()).toString());
return (Criteria) this;
}
public Criteria andSessionKeyNotEqualTo(String value) {
addCriterion("session_key <>", value, "sessionKey");
return (Criteria) this;
}
/**
* This method was generated by MyBatis Generator.
* This method corresponds to the database table litemall_user
*
* @mbg.generated
* @project https://github.com/itfsw/mybatis-generator-plugin
*/
public Criteria andSessionKeyNotEqualToColumn(LitemallUser.Column column) {
addCriterion(new StringBuilder("session_key <> ").append(column.getEscapedColumnName()).toString());
return (Criteria) this;
}
public Criteria andSessionKeyGreaterThan(String value) {
addCriterion("session_key >", value, "sessionKey");
return (Criteria) this;
}
/**
* This method was generated by MyBatis Generator.
* This method corresponds to the database table litemall_user
*
* @mbg.generated
* @project https://github.com/itfsw/mybatis-generator-plugin
*/
public Criteria andSessionKeyGreaterThanColumn(LitemallUser.Column column) {
addCriterion(new StringBuilder("session_key > ").append(column.getEscapedColumnName()).toString());
return (Criteria) this;
}
public Criteria andSessionKeyGreaterThanOrEqualTo(String value) {
addCriterion("session_key >=", value, "sessionKey");
return (Criteria) this;
}
/**
* This method was generated by MyBatis Generator.
* This method corresponds to the database table litemall_user
*
* @mbg.generated
* @project https://github.com/itfsw/mybatis-generator-plugin
*/
public Criteria andSessionKeyGreaterThanOrEqualToColumn(LitemallUser.Column column) {
addCriterion(new StringBuilder("session_key >= ").append(column.getEscapedColumnName()).toString());
return (Criteria) this;
}
public Criteria andSessionKeyLessThan(String value) {
addCriterion("session_key <", value, "sessionKey");
return (Criteria) this;
}
/**
* This method was generated by MyBatis Generator.
* This method corresponds to the database table litemall_user
*
* @mbg.generated
* @project https://github.com/itfsw/mybatis-generator-plugin
*/
public Criteria andSessionKeyLessThanColumn(LitemallUser.Column column) {
addCriterion(new StringBuilder("session_key < ").append(column.getEscapedColumnName()).toString());
return (Criteria) this;
}
public Criteria andSessionKeyLessThanOrEqualTo(String value) {
addCriterion("session_key <=", value, "sessionKey");
return (Criteria) this;
}
/**
* This method was generated by MyBatis Generator.
* This method corresponds to the database table litemall_user
*
* @mbg.generated
* @project https://github.com/itfsw/mybatis-generator-plugin
*/
public Criteria andSessionKeyLessThanOrEqualToColumn(LitemallUser.Column column) {
addCriterion(new StringBuilder("session_key <= ").append(column.getEscapedColumnName()).toString());
return (Criteria) this;
}
public Criteria andSessionKeyLike(String value) {
addCriterion("session_key like", value, "sessionKey");
return (Criteria) this;
}
public Criteria andSessionKeyNotLike(String value) {
addCriterion("session_key not like", value, "sessionKey");
return (Criteria) this;
}
public Criteria andSessionKeyIn(List<String> values) {
addCriterion("session_key in", values, "sessionKey");
return (Criteria) this;
}
public Criteria andSessionKeyNotIn(List<String> values) {
addCriterion("session_key not in", values, "sessionKey");
return (Criteria) this;
}
public Criteria andSessionKeyBetween(String value1, String value2) {
addCriterion("session_key between", value1, value2, "sessionKey");
return (Criteria) this;
}
public Criteria andSessionKeyNotBetween(String value1, String value2) {
addCriterion("session_key not between", value1, value2, "sessionKey");
return (Criteria) this;
}
public Criteria andStatusIsNull() {
addCriterion("`status` is null");
return (Criteria) this;
......
......@@ -18,6 +18,7 @@
<result column="mobile" jdbcType="VARCHAR" property="mobile" />
<result column="avatar" jdbcType="VARCHAR" property="avatar" />
<result column="weixin_openid" jdbcType="VARCHAR" property="weixinOpenid" />
<result column="session_key" jdbcType="VARCHAR" property="sessionKey" />
<result column="status" jdbcType="TINYINT" property="status" />
<result column="add_time" jdbcType="TIMESTAMP" property="addTime" />
<result column="update_time" jdbcType="TIMESTAMP" property="updateTime" />
......@@ -95,7 +96,8 @@
This element is automatically generated by MyBatis Generator, do not modify.
-->
id, username, `password`, gender, birthday, last_login_time, last_login_ip, user_level,
nickname, mobile, avatar, weixin_openid, `status`, add_time, update_time, deleted
nickname, mobile, avatar, weixin_openid, session_key, `status`, add_time, update_time,
deleted
</sql>
<select id="selectByExample" parameterType="org.linlinjava.litemall.db.domain.LitemallUserExample" resultMap="BaseResultMap">
<!--
......@@ -133,8 +135,8 @@
</when>
<otherwise>
id, username, `password`, gender, birthday, last_login_time, last_login_ip, user_level,
nickname, mobile, avatar, weixin_openid, `status`, add_time, update_time, deleted
nickname, mobile, avatar, weixin_openid, session_key, `status`, add_time, update_time,
deleted
</otherwise>
</choose>
from litemall_user
......@@ -194,8 +196,8 @@
</when>
<otherwise>
id, username, `password`, gender, birthday, last_login_time, last_login_ip, user_level,
nickname, mobile, avatar, weixin_openid, `status`, add_time, update_time, deleted
nickname, mobile, avatar, weixin_openid, session_key, `status`, add_time, update_time,
deleted
</otherwise>
</choose>
from litemall_user
......@@ -230,15 +232,15 @@
insert into litemall_user (username, `password`, gender,
birthday, last_login_time, last_login_ip,
user_level, nickname, mobile,
avatar, weixin_openid, `status`,
add_time, update_time, deleted
)
avatar, weixin_openid, session_key,
`status`, add_time, update_time,
deleted)
values (#{username,jdbcType=VARCHAR}, #{password,jdbcType=VARCHAR}, #{gender,jdbcType=TINYINT},
#{birthday,jdbcType=DATE}, #{lastLoginTime,jdbcType=TIMESTAMP}, #{lastLoginIp,jdbcType=VARCHAR},
#{userLevel,jdbcType=TINYINT}, #{nickname,jdbcType=VARCHAR}, #{mobile,jdbcType=VARCHAR},
#{avatar,jdbcType=VARCHAR}, #{weixinOpenid,jdbcType=VARCHAR}, #{status,jdbcType=TINYINT},
#{addTime,jdbcType=TIMESTAMP}, #{updateTime,jdbcType=TIMESTAMP}, #{deleted,jdbcType=BIT}
)
#{avatar,jdbcType=VARCHAR}, #{weixinOpenid,jdbcType=VARCHAR}, #{sessionKey,jdbcType=VARCHAR},
#{status,jdbcType=TINYINT}, #{addTime,jdbcType=TIMESTAMP}, #{updateTime,jdbcType=TIMESTAMP},
#{deleted,jdbcType=BIT})
</insert>
<insert id="insertSelective" parameterType="org.linlinjava.litemall.db.domain.LitemallUser">
<!--
......@@ -283,6 +285,9 @@
<if test="weixinOpenid != null">
weixin_openid,
</if>
<if test="sessionKey != null">
session_key,
</if>
<if test="status != null">
`status`,
</if>
......@@ -330,6 +335,9 @@
<if test="weixinOpenid != null">
#{weixinOpenid,jdbcType=VARCHAR},
</if>
<if test="sessionKey != null">
#{sessionKey,jdbcType=VARCHAR},
</if>
<if test="status != null">
#{status,jdbcType=TINYINT},
</if>
......@@ -397,6 +405,9 @@
<if test="record.weixinOpenid != null">
weixin_openid = #{record.weixinOpenid,jdbcType=VARCHAR},
</if>
<if test="record.sessionKey != null">
session_key = #{record.sessionKey,jdbcType=VARCHAR},
</if>
<if test="record.status != null">
`status` = #{record.status,jdbcType=TINYINT},
</if>
......@@ -432,6 +443,7 @@
mobile = #{record.mobile,jdbcType=VARCHAR},
avatar = #{record.avatar,jdbcType=VARCHAR},
weixin_openid = #{record.weixinOpenid,jdbcType=VARCHAR},
session_key = #{record.sessionKey,jdbcType=VARCHAR},
`status` = #{record.status,jdbcType=TINYINT},
add_time = #{record.addTime,jdbcType=TIMESTAMP},
update_time = #{record.updateTime,jdbcType=TIMESTAMP},
......@@ -480,6 +492,9 @@
<if test="weixinOpenid != null">
weixin_openid = #{weixinOpenid,jdbcType=VARCHAR},
</if>
<if test="sessionKey != null">
session_key = #{sessionKey,jdbcType=VARCHAR},
</if>
<if test="status != null">
`status` = #{status,jdbcType=TINYINT},
</if>
......@@ -512,6 +527,7 @@
mobile = #{mobile,jdbcType=VARCHAR},
avatar = #{avatar,jdbcType=VARCHAR},
weixin_openid = #{weixinOpenid,jdbcType=VARCHAR},
session_key = #{sessionKey,jdbcType=VARCHAR},
`status` = #{status,jdbcType=TINYINT},
add_time = #{addTime,jdbcType=TIMESTAMP},
update_time = #{updateTime,jdbcType=TIMESTAMP},
......@@ -550,8 +566,8 @@
</when>
<otherwise>
id, username, `password`, gender, birthday, last_login_time, last_login_ip, user_level,
nickname, mobile, avatar, weixin_openid, `status`, add_time, update_time, deleted
nickname, mobile, avatar, weixin_openid, session_key, `status`, add_time, update_time,
deleted
</otherwise>
</choose>
from litemall_user
......
......@@ -48,6 +48,12 @@
<groupId>com.github.binarywang</groupId>
<artifactId>weixin-java-miniapp</artifactId>
</dependency>
<dependency>
<groupId>com.auth0</groupId>
<artifactId>java-jwt</artifactId>
<version>3.4.1</version>
</dependency>
</dependencies>
......
package org.linlinjava.litemall.wx.service;
import org.linlinjava.litemall.core.util.CharUtil;
import org.linlinjava.litemall.wx.dto.UserToken;
import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.Map;
import org.linlinjava.litemall.wx.util.JwtHelper;
/**
* 维护用户token
*/
public class UserTokenManager {
private static Map<String, UserToken> tokenMap = new HashMap<>();
private static Map<Integer, UserToken> idMap = new HashMap<>();
public static Integer getUserId(String token) {
UserToken userToken = tokenMap.get(token);
if (userToken == null) {
return null;
}
if (userToken.getExpireTime().isBefore(LocalDateTime.now())) {
tokenMap.remove(token);
idMap.remove(userToken.getUserId());
return null;
}
return userToken.getUserId();
public static String generateToken(Integer id) {
JwtHelper jwtHelper = new JwtHelper();
return jwtHelper.createToken(id);
}
public static UserToken generateToken(Integer id) {
UserToken userToken = null;
// userToken = idMap.get(id);
// if(userToken != null) {
// tokenMap.remove(userToken.getToken());
// idMap.remove(id);
// }
String token = CharUtil.getRandomString(32);
while (tokenMap.containsKey(token)) {
token = CharUtil.getRandomString(32);
}
LocalDateTime update = LocalDateTime.now();
LocalDateTime expire = update.plusDays(1);
userToken = new UserToken();
userToken.setToken(token);
userToken.setUpdateTime(update);
userToken.setExpireTime(expire);
userToken.setUserId(id);
tokenMap.put(token, userToken);
idMap.put(id, userToken);
return userToken;
}
public static String getSessionKey(Integer userId) {
UserToken userToken = idMap.get(userId);
if (userToken == null) {
return null;
}
if (userToken.getExpireTime().isBefore(LocalDateTime.now())) {
tokenMap.remove(userToken.getToken());
idMap.remove(userId);
return null;
}
return userToken.getSessionKey();
}
public static void removeToken(Integer userId) {
UserToken userToken = idMap.get(userId);
String token = userToken.getToken();
idMap.remove(userId);
tokenMap.remove(token);
public static Integer getUserId(String token) {
JwtHelper jwtHelper = new JwtHelper();
Integer userId = jwtHelper.verifyTokenAndGetUserId(token);
if(userId == null || userId == 0){
return null;
}
return userId;
}
}
package org.linlinjava.litemall.wx.util;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.HashMap;
import java.util.Map;
import com.auth0.jwt.JWT;
import com.auth0.jwt.JWTVerifier;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.exceptions.JWTCreationException;
import com.auth0.jwt.exceptions.JWTVerificationException;
import com.auth0.jwt.interfaces.Claim;
import com.auth0.jwt.interfaces.DecodedJWT;
public class JwtHelper {
// 秘钥
static final String SECRET = "X-Litemall-Token";
// 签名是有谁生成
static final String ISSUSER = "LITEMALL";
// 签名的主题
static final String SUBJECT = "this is litemall token";
// 签名的观众
static final String AUDIENCE = "MINIAPP";
public String createToken(Integer userId){
try {
Algorithm algorithm = Algorithm.HMAC256(SECRET);
Map<String, Object> map = new HashMap<String, Object>();
Date nowDate = new Date();
// 过期时间:2小时
Date expireDate = getAfterDate(nowDate,0,0,0,2,0,0);
map.put("alg", "HS256");
map.put("typ", "JWT");
String token = JWT.create()
// 设置头部信息 Header
.withHeader(map)
// 设置 载荷 Payload
.withClaim("userId", userId)
.withIssuer(ISSUSER)
.withSubject(SUBJECT)
.withAudience(AUDIENCE)
// 生成签名的时间
.withIssuedAt(nowDate)
// 签名过期的时间
.withExpiresAt(expireDate)
// 签名 Signature
.sign(algorithm);
return token;
} catch (JWTCreationException exception){
exception.printStackTrace();
}
return null;
}
public Integer verifyTokenAndGetUserId(String token) {
try {
Algorithm algorithm = Algorithm.HMAC256(SECRET);
JWTVerifier verifier = JWT.require(algorithm)
.withIssuer(ISSUSER)
.build();
DecodedJWT jwt = verifier.verify(token);
Map<String, Claim> claims = jwt.getClaims();
Claim claim = claims.get("userId");
return claim.asInt();
} catch (JWTVerificationException exception){
// exception.printStackTrace();
}
return 0;
}
public Date getAfterDate(Date date, int year, int month, int day, int hour, int minute, int second){
if(date == null){
date = new Date();
}
Calendar cal = new GregorianCalendar();
cal.setTime(date);
if(year != 0){
cal.add(Calendar.YEAR, year);
}
if(month != 0){
cal.add(Calendar.MONTH, month);
}
if(day != 0){
cal.add(Calendar.DATE, day);
}
if(hour != 0){
cal.add(Calendar.HOUR_OF_DAY, hour);
}
if(minute != 0){
cal.add(Calendar.MINUTE, minute);
}
if(second != 0){
cal.add(Calendar.SECOND, second);
}
return cal.getTime();
}
}
......@@ -95,11 +95,10 @@ public class WxAuthController {
userInfo.setAvatarUrl(user.getAvatar());
// token
UserToken userToken = UserTokenManager.generateToken(user.getId());
String token = UserTokenManager.generateToken(user.getId());
Map<Object, Object> result = new HashMap<Object, Object>();
result.put("token", userToken.getToken());
result.put("tokenExpire", userToken.getExpireTime().toString());
result.put("token", token);
result.put("userInfo", userInfo);
return ResponseUtil.ok(result);
}
......@@ -146,6 +145,7 @@ public class WxAuthController {
user.setStatus((byte) 0);
user.setLastLoginTime(LocalDateTime.now());
user.setLastLoginIp(IpUtil.getIpAddr(request));
user.setSessionKey(sessionKey);
userService.add(user);
......@@ -154,18 +154,17 @@ public class WxAuthController {
} else {
user.setLastLoginTime(LocalDateTime.now());
user.setLastLoginIp(IpUtil.getIpAddr(request));
user.setSessionKey(sessionKey);
if (userService.updateById(user) == 0) {
return ResponseUtil.updatedDataFailed();
}
}
// token
UserToken userToken = UserTokenManager.generateToken(user.getId());
userToken.setSessionKey(sessionKey);
String token = UserTokenManager.generateToken(user.getId());
Map<Object, Object> result = new HashMap<Object, Object>();
result.put("token", userToken.getToken());
result.put("tokenExpire", userToken.getExpireTime().toString());
result.put("token", token);
result.put("userInfo", userInfo);
return ResponseUtil.ok(result);
}
......@@ -305,11 +304,10 @@ public class WxAuthController {
userInfo.setAvatarUrl(user.getAvatar());
// token
UserToken userToken = UserTokenManager.generateToken(user.getId());
String token = UserTokenManager.generateToken(user.getId());
Map<Object, Object> result = new HashMap<Object, Object>();
result.put("token", userToken.getToken());
result.put("tokenExpire", userToken.getExpireTime().toString());
result.put("token", token);
result.put("userInfo", userInfo);
return ResponseUtil.ok(result);
}
......@@ -367,12 +365,14 @@ public class WxAuthController {
@PostMapping("bindPhone")
public Object bindPhone(@LoginUser Integer userId, @RequestBody String body) {
String sessionKey = UserTokenManager.getSessionKey(userId);
if (userId == null) {
return ResponseUtil.unlogin();
}
LitemallUser user = userService.findById(userId);
String encryptedData = JacksonUtil.parseString(body, "encryptedData");
String iv = JacksonUtil.parseString(body, "iv");
WxMaPhoneNumberInfo phoneNumberInfo = this.wxService.getUserService().getPhoneNoInfo(sessionKey, encryptedData, iv);
WxMaPhoneNumberInfo phoneNumberInfo = this.wxService.getUserService().getPhoneNoInfo(user.getSessionKey(), encryptedData, iv);
String phone = phoneNumberInfo.getPhoneNumber();
LitemallUser user = userService.findById(userId);
user.setMobile(phone);
if (userService.updateById(user) == 0) {
return ResponseUtil.updatedDataFailed();
......@@ -385,7 +385,6 @@ public class WxAuthController {
if (userId == null) {
return ResponseUtil.unlogin();
}
UserTokenManager.removeToken(userId);
return ResponseUtil.ok();
}
}
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment