在分布式环境中,如何支持PC、APP(ios、android)等多端的会话共享,这也是所有公司都需要的解决方案,用传统的session方式来解决,我想已经out了,我们是否可以找一个通用的方案,比如用传统cas来实现多系统之间的sso单点登录或使用oauth的第三方登录方案? 今天给大家简单讲解一下使用spring拦截器Interceptor机制、jwt认证方式、redis分布式缓存实现sso单点登录,闲话少说,直接把步骤记录下来分享给大家:
- 引入jwt的相关jar包,在项目pom.xml中引入:
Java代码
- <dependency>
- <groupId>com.auth0</groupId>
- <artifactId>java-jwt</artifactId>
- <version>
2.2.
0</version>
-
</dependency>
1
2
3
4
5
6 1<dependency>
2 <groupId>com.auth0</groupId>
3 <artifactId>java-jwt</artifactId>
4 <version>2.2.0</version>
5</dependency>
6
- 拦截器配置:
Java代码
- mvc:interceptor
- <mvc:mapping path=
"${adminPath}/**" />
- <mvc:exclude-mapping path=
"${adminPath}/rest/login"/>
- <bean
class=
"com.ml.honghu.interceptor.LoginInterceptor" />
-
</mvc:interceptor>
1
2
3
4
5
6 1<mvc:interceptor>
2 <mvc:mapping path="${adminPath}/**" />
3 <mvc:exclude-mapping path="${adminPath}/rest/login"/>
4 <bean class="com.ml.honghu.interceptor.LoginInterceptor" />
5</mvc:interceptor>
6
我这里简单配置了要拦截的url和过滤的url(这个根据自己项目来定)
- 编写jwt的加密或者解密工具类:
Java代码
- public
class JWT {
private
static
final String SECRET =
"HONGHUJWT1234567890QWERTYUIOPASDFGHJKLZXCVBNM";
private
static
final String EXP =
"exp";
private
static
final String PAYLOAD =
"payload";
//加密
public
static <T> String sign(T object,
long maxAge) {
try {
final JWTSigner signer =
new JWTSigner(SECRET);
final Map<String, Object> claims =
new HashMap<String, Object>();
- ObjectMapper mapper =
new ObjectMapper();
- String jsonString = mapper.writeValueAsString(object);
- claims.put(PAYLOAD, jsonString);
- claims.put(EXP, System.currentTimeMillis() + maxAge);
return signer.sign(claims);
- }
catch(Exception e) {
return
null;
- }
- }
//解密
public
static<T> T unsign(String jwt, Class<T> classT) {
final JWTVerifier verifier =
new JWTVerifier(SECRET);
try {
final Map<String,Object> claims= verifier.verify(jwt);
if (claims.containsKey(EXP) && claims.containsKey(PAYLOAD)) {
- String json = (String)claims.get(PAYLOAD);
- ObjectMapper objectMapper =
new ObjectMapper();
return objectMapper.readValue(json, classT);
- }
return
null;
- }
catch (Exception e) {
return
null;
-
}
-
}
-
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40 1public class JWT {
2 private static final String SECRET = "HONGHUJWT1234567890QWERTYUIOPASDFGHJKLZXCVBNM";
3
4 private static final String EXP = "exp";
5
6 private static final String PAYLOAD = "payload";
7
8 //加密
9 public static <T> String sign(T object, long maxAge) {
10 try {
11 final JWTSigner signer = new JWTSigner(SECRET);
12 final Map<String, Object> claims = new HashMap<String, Object>();
13 ObjectMapper mapper = new ObjectMapper();
14 String jsonString = mapper.writeValueAsString(object);
15 claims.put(PAYLOAD, jsonString);
16 claims.put(EXP, System.currentTimeMillis() + maxAge);
17 return signer.sign(claims);
18 } catch(Exception e) {
19 return null;
20 }
21 }
22
23 //解密
24 public static<T> T unsign(String jwt, Class<T> classT) {
25 final JWTVerifier verifier = new JWTVerifier(SECRET);
26 try {
27 final Map<String,Object> claims= verifier.verify(jwt);
28 if (claims.containsKey(EXP) && claims.containsKey(PAYLOAD)) {
29 String json = (String)claims.get(PAYLOAD);
30 ObjectMapper objectMapper = new ObjectMapper();
31 return objectMapper.readValue(json, classT);
32
33 }
34 return null;
35 } catch (Exception e) {
36 return null;
37 }
38 }
39}
40
这个加密工具类是我从网上找的,如果各位要修改,可以按照自己业务修改即可。
- 创建Login.java对象,用来进行jwt的加密或者解密:
Java代码
- public
class Login
implements Serializable{
/**
- *
- */
private
static
final
long serialVersionUID = 1899232511233819216L;
/**
- * 用户id
- */
private String uid;
/**
- * 登录用户名
- */
private String loginName;
/**
- * 登录密码
- */
private String password;
public Login(){
super();
- }
public Login(String uid, String loginName, String password){
this.uid = uid;
this.loginName = loginName;
this.password = password;
- }
public String getUid() {
return uid;
- }
public
void setUid(String uid) {
this.uid = uid;
- }
public String getLoginName() {
return loginName;
- }
public
void setLoginName(String loginName) {
this.loginName = loginName;
- }
public String getPassword() {
return password;
- }
public
void setPassword(String password) {
this.password = password;
-
}
-
-
-
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53 1public class Login implements Serializable{
2 /**
3 *
4 */
5 private static final long serialVersionUID = 1899232511233819216L;
6
7 /**
8 * 用户id
9 */
10 private String uid;
11
12 /**
13 * 登录用户名
14 */
15 private String loginName;
16
17 /**
18 * 登录密码
19 */
20 private String password;
21
22 public Login(){
23 super();
24 }
25
26 public Login(String uid, String loginName, String password){
27 this.uid = uid;
28 this.loginName = loginName;
29 this.password = password;
30 }
31
32 public String getUid() {
33 return uid;
34 }
35 public void setUid(String uid) {
36 this.uid = uid;
37 }
38 public String getLoginName() {
39 return loginName;
40 }
41 public void setLoginName(String loginName) {
42 this.loginName = loginName;
43 }
44 public String getPassword() {
45 return password;
46 }
47 public void setPassword(String password) {
48 this.password = password;
49 }
50
51
52}
53
- 定义RedisLogin对象,用来通过uid往redis进行user对象存储:
Java代码
- public
class RedisLogin
implements Serializable{
/**
- *
- */
private
static
final
long serialVersionUID = 8116817810829835862L;
/**
- * 用户id
- */
private String uid;
/**
- * jwt生成的token信息
- */
private String token;
/**
- * 登录或刷新应用的时间
- */
private
long refTime;
public RedisLogin(){
- }
public RedisLogin(String uid, String token,
long refTime){
this.uid = uid;
this.token = token;
this.refTime = refTime;
- }
public String getUid() {
return uid;
- }
public
void setUid(String uid) {
this.uid = uid;
- }
public String getToken() {
return token;
- }
public
void setToken(String token) {
this.token = token;
- }
public
long getRefTime() {
return refTime;
- }
public
void setRefTime(
long refTime) {
this.refTime = refTime;
-
}
-
-
-
-
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54 1public class RedisLogin implements Serializable{
2 /**
3 *
4 */
5 private static final long serialVersionUID = 8116817810829835862L;
6
7 /**
8 * 用户id
9 */
10 private String uid;
11
12 /**
13 * jwt生成的token信息
14 */
15 private String token;
16
17 /**
18 * 登录或刷新应用的时间
19 */
20 private long refTime;
21
22 public RedisLogin(){
23
24 }
25
26 public RedisLogin(String uid, String token, long refTime){
27 this.uid = uid;
28 this.token = token;
29 this.refTime = refTime;
30 }
31
32 public String getUid() {
33 return uid;
34 }
35 public void setUid(String uid) {
36 this.uid = uid;
37 }
38 public String getToken() {
39 return token;
40 }
41 public void setToken(String token) {
42 this.token = token;
43 }
44 public long getRefTime() {
45 return refTime;
46 }
47 public void setRefTime(long refTime) {
48 this.refTime = refTime;
49 }
50
51
52
53}
54
- 编写LoginInterceptor.java拦截器
Java代码
- public
class LoginInterceptor
implements HandlerInterceptor{
public
boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
throws Exception {
- PrintWriter writer =
null;
- HandlerMethod method =
null;
try {
- method = (HandlerMethod) handler;
- }
catch (Exception e) {
- writer = response.getWriter();
- ResponseVO responseVO = ResponseCode.buildEnumResponseVO(ResponseCode.REQUEST_URL_NOT_SERVICE,
false);
- responseMessage(response, writer, responseVO);
return
false;
- }
- IsLogin isLogin = method.getMethodAnnotation(IsLogin.
class);
if(
null == isLogin){
return
true;
- }
- response.setCharacterEncoding(
"utf-8");
- String token = request.getHeader(
"token");
- String uid = request.getHeader(
"uid");
//token不存在
if(StringUtils.isEmpty(token)) {
- writer = response.getWriter();
- ResponseVO responseVO = LoginResponseCode.buildEnumResponseVO(LoginResponseCode.LOGIN_TOKEN_NOT_NULL,
false);
- responseMessage(response, writer, responseVO);
return
false;
- }
if(StringUtils.isEmpty(uid)){
- writer = response.getWriter();
- ResponseVO responseVO = LoginResponseCode.buildEnumResponseVO(LoginResponseCode.USERID_NOT_NULL,
false);
- responseMessage(response, writer, responseVO);
return
false;
- }
- Login login = JWT.unsign(token, Login.
class);
//解密token后的loginId与用户传来的loginId判断是否一致
if(
null == login || !StringUtils.equals(login.getUid(), uid)){
- writer = response.getWriter();
- ResponseVO responseVO = LoginResponseCode.buildEnumResponseVO(LoginResponseCode.USERID_NOT_UNAUTHORIZED,
false);
- responseMessage(response, writer, responseVO);
return
false;
- }
//验证登录时间
- RedisLogin redisLogin = (RedisLogin)JedisUtils.getObject(uid);
if(
null == redisLogin){
- writer = response.getWriter();
- ResponseVO responseVO = LoginResponseCode.buildEnumResponseVO(LoginResponseCode.RESPONSE_CODE_UNLOGIN_ERROR,
false);
- responseMessage(response, writer, responseVO);
return
false;
- }
if(!StringUtils.equals(token, redisLogin.getToken())){
- writer = response.getWriter();
- ResponseVO responseVO = LoginResponseCode.buildEnumResponseVO(LoginResponseCode.USERID_NOT_UNAUTHORIZED,
false);
- responseMessage(response, writer, responseVO);
return
false;
- }
//系统时间>有效期(说明已经超过有效期)
if (System.currentTimeMillis() > redisLogin.getRefTime()) {
- writer = response.getWriter();
- ResponseVO responseVO = LoginResponseCode.buildEnumResponseVO(LoginResponseCode.LOGIN_TIME_EXP,
false);
- responseMessage(response, writer, responseVO);
return
false;
- }
//重新刷新有效期
- redisLogin =
new RedisLogin(uid, token, System.currentTimeMillis() + 60L* 1000L* 30L);
- JedisUtils.setObject(uid , redisLogin,
360000000);
return
true;
- }
public
void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
- ModelAndView modelAndView)
throws Exception {
- }
public
void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
throws Exception {
- }
private
void responseMessage(HttpServletResponse response, PrintWriter out, ResponseVO responseVO) {
- response.setContentType(
"application/json; charset=utf-8");
- JSONObject result =
new JSONObject();
- result.put(
"result", responseVO);
-
out.print(result);
-
out.flush();
-
out.close();
-
}
-
-
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96 1public class LoginInterceptor implements HandlerInterceptor{
2
3 public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
4 throws Exception {
5 PrintWriter writer = null;
6 HandlerMethod method = null;
7 try {
8 method = (HandlerMethod) handler;
9 } catch (Exception e) {
10 writer = response.getWriter();
11 ResponseVO responseVO = ResponseCode.buildEnumResponseVO(ResponseCode.REQUEST_URL_NOT_SERVICE, false);
12 responseMessage(response, writer, responseVO);
13 return false;
14 }
15 IsLogin isLogin = method.getMethodAnnotation(IsLogin.class);
16 if(null == isLogin){
17 return true;
18 }
19
20
21 response.setCharacterEncoding("utf-8");
22 String token = request.getHeader("token");
23 String uid = request.getHeader("uid");
24 //token不存在
25 if(StringUtils.isEmpty(token)) {
26 writer = response.getWriter();
27 ResponseVO responseVO = LoginResponseCode.buildEnumResponseVO(LoginResponseCode.LOGIN_TOKEN_NOT_NULL, false);
28 responseMessage(response, writer, responseVO);
29 return false;
30 }
31 if(StringUtils.isEmpty(uid)){
32 writer = response.getWriter();
33 ResponseVO responseVO = LoginResponseCode.buildEnumResponseVO(LoginResponseCode.USERID_NOT_NULL, false);
34 responseMessage(response, writer, responseVO);
35 return false;
36 }
37
38 Login login = JWT.unsign(token, Login.class);
39 //解密token后的loginId与用户传来的loginId判断是否一致
40 if(null == login || !StringUtils.equals(login.getUid(), uid)){
41 writer = response.getWriter();
42 ResponseVO responseVO = LoginResponseCode.buildEnumResponseVO(LoginResponseCode.USERID_NOT_UNAUTHORIZED, false);
43 responseMessage(response, writer, responseVO);
44 return false;
45 }
46
47 //验证登录时间
48 RedisLogin redisLogin = (RedisLogin)JedisUtils.getObject(uid);
49 if(null == redisLogin){
50 writer = response.getWriter();
51 ResponseVO responseVO = LoginResponseCode.buildEnumResponseVO(LoginResponseCode.RESPONSE_CODE_UNLOGIN_ERROR, false);
52 responseMessage(response, writer, responseVO);
53 return false;
54 }
55
56 if(!StringUtils.equals(token, redisLogin.getToken())){
57 writer = response.getWriter();
58 ResponseVO responseVO = LoginResponseCode.buildEnumResponseVO(LoginResponseCode.USERID_NOT_UNAUTHORIZED, false);
59 responseMessage(response, writer, responseVO);
60 return false;
61 }
62 //系统时间>有效期(说明已经超过有效期)
63 if (System.currentTimeMillis() > redisLogin.getRefTime()) {
64 writer = response.getWriter();
65 ResponseVO responseVO = LoginResponseCode.buildEnumResponseVO(LoginResponseCode.LOGIN_TIME_EXP, false);
66 responseMessage(response, writer, responseVO);
67 return false;
68 }
69
70 //重新刷新有效期
71 redisLogin = new RedisLogin(uid, token, System.currentTimeMillis() + 60L* 1000L* 30L);
72 JedisUtils.setObject(uid , redisLogin, 360000000);
73 return true;
74 }
75
76 public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
77 ModelAndView modelAndView) throws Exception {
78
79 }
80
81 public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
82 throws Exception {
83
84 }
85
86 private void responseMessage(HttpServletResponse response, PrintWriter out, ResponseVO responseVO) {
87 response.setContentType("application/json; charset=utf-8");
88 JSONObject result = new JSONObject();
89 result.put("result", responseVO);
90 out.print(result);
91 out.flush();
92 out.close();
93 }
94
95}
96
- 定义异常的LoginResponseCode
Java代码
- public
enum LoginResponseCode {
- USERID_NOT_NULL(
3001,
"用户id不能为空."),
- LOGIN_TOKEN_NOT_NULL(
3002,
"登录token不能为空."),
- USERID_NOT_UNAUTHORIZED(
3003,
"用户token或ID验证不通过"),
- RESPONSE_CODE_UNLOGIN_ERROR(
421,
"未登录异常"),
- LOGIN_TIME_EXP(
3004,
"登录时间超长,请重新登录");
// 成员变量
private
int code;
//状态码
private String message;
//返回消息
// 构造方法
private LoginResponseCode(
int code,String message) {
this.code = code;
this.message = message;
- }
public
int getCode() {
return code;
- }
public
void setCode(
int code) {
this.code = code;
- }
public String getMessage() {
return message;
- }
public
void setMessage(String message) {
this.message = message;
- }
public
static ResponseVO buildEnumResponseVO(LoginResponseCode responseCode, Object data) {
return
new ResponseVO(responseCode.getCode(),responseCode.getMessage(),data);
- }
public
static Map<String, Object> buildReturnMap(LoginResponseCode responseCode, Object data) {
- Map<String, Object> map =
new HashMap<String, Object>();
- map.put(
"code", responseCode.getCode());
- map.put(
"message", responseCode.getMessage());
- map.put(
"data", data);
return map;
-
}
-
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42 1public enum LoginResponseCode {
2 USERID_NOT_NULL(3001,"用户id不能为空."),
3 LOGIN_TOKEN_NOT_NULL(3002,"登录token不能为空."),
4 USERID_NOT_UNAUTHORIZED(3003, "用户token或ID验证不通过"),
5 RESPONSE_CODE_UNLOGIN_ERROR(421, "未登录异常"),
6 LOGIN_TIME_EXP(3004, "登录时间超长,请重新登录");
7
8 // 成员变量
9 private int code; //状态码
10 private String message; //返回消息
11
12 // 构造方法
13 private LoginResponseCode(int code,String message) {
14 this.code = code;
15 this.message = message;
16 }
17 public int getCode() {
18 return code;
19 }
20 public void setCode(int code) {
21 this.code = code;
22 }
23 public String getMessage() {
24 return message;
25 }
26 public void setMessage(String message) {
27 this.message = message;
28 }
29
30 public static ResponseVO buildEnumResponseVO(LoginResponseCode responseCode, Object data) {
31 return new ResponseVO(responseCode.getCode(),responseCode.getMessage(),data);
32 }
33
34 public static Map<String, Object> buildReturnMap(LoginResponseCode responseCode, Object data) {
35 Map<String, Object> map = new HashMap<String, Object>();
36 map.put("code", responseCode.getCode());
37 map.put("message", responseCode.getMessage());
38 map.put("data", data);
39 return map;
40 }
41}
42
- 编写统一sso单点登录接口:
Java代码
- @RequestMapping(value =
"/login", method = RequestMethod.POST)
public Map<String, Object> login(
@RequestBody JSONObject json){
- String loginName = json.optString(
"loginName");
- String password = json.optString(
"password");
//校验用户名不能为空
if(StringUtils.isEmpty(loginName)){
return MemberResponseCode.buildReturnMap(MemberResponseCode.RESPONSE_CODE_USER_NAME_IS_NOT_EMPTY,
null);
- }
//校验用户密码不能为空
if(StringUtils.isEmpty(password)){
return MemberResponseCode.buildReturnMap(MemberResponseCode.RESPONSE_CODE_PWD_CAN_NOT_BE_EMPTY,
null);
- }
//根据用户名查询数据库用户信息
- User user = systemService.getBaseUserByLoginName(loginName);
//用户名或密码不正确
if(
null == user){
return MemberResponseCode.buildReturnMap(MemberResponseCode.RESPONSE_CODE_USER_VALIDATE_NO_SUCCESS,
false);
- }
boolean isValidate = systemService.validatePassword(password, user.getPassword());
if(!isValidate){
return MemberResponseCode.buildReturnMap(MemberResponseCode.RESPONSE_CODE_USER_VALIDATE_NO_SUCCESS,
false);
- }
if(isValidate){
//HttpSession session =request.getSession(false);
- Login login =
new Login(user.getId(), user.getLoginName(), user.getPassword());
//给用户jwt加密生成token
- String token = JWT.sign(login, 60L* 1000L* 30L);
- Map<String,Object> result =
new HashMap<String,Object>();
- result.put(
"loginToken", token);
- result.put(
"userId", user.getId());
- result.put(
"user", user);
//保存用户信息到session
//session.setAttribute(user.getId() + "@@" + token, user);
//重建用户信息
this.rebuildLoginUser(user.getId(), token);
return ResponseCode.buildReturnMap(ResponseCode.RESPONSE_CODE_LOGIN_SUCCESS, result);
- }
return ResponseCode.buildReturnMap(ResponseCode.USER_LOGIN_PWD_ERROR,
false);
-
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42 1@RequestMapping(value = "/login", method = RequestMethod.POST)
2 public Map<String, Object> login(@RequestBody JSONObject json){
3 String loginName = json.optString("loginName");
4 String password = json.optString("password");
5 //校验用户名不能为空
6 if(StringUtils.isEmpty(loginName)){
7 return MemberResponseCode.buildReturnMap(MemberResponseCode.RESPONSE_CODE_USER_NAME_IS_NOT_EMPTY, null);
8 }
9 //校验用户密码不能为空
10 if(StringUtils.isEmpty(password)){
11 return MemberResponseCode.buildReturnMap(MemberResponseCode.RESPONSE_CODE_PWD_CAN_NOT_BE_EMPTY, null);
12 }
13 //根据用户名查询数据库用户信息
14 User user = systemService.getBaseUserByLoginName(loginName);
15 //用户名或密码不正确
16 if(null == user){
17 return MemberResponseCode.buildReturnMap(MemberResponseCode.RESPONSE_CODE_USER_VALIDATE_NO_SUCCESS, false);
18 }
19 boolean isValidate = systemService.validatePassword(password, user.getPassword());
20 if(!isValidate){
21 return MemberResponseCode.buildReturnMap(MemberResponseCode.RESPONSE_CODE_USER_VALIDATE_NO_SUCCESS, false);
22 }
23 if(isValidate){
24 //HttpSession session =request.getSession(false);
25 Login login = new Login(user.getId(), user.getLoginName(), user.getPassword());
26 //给用户jwt加密生成token
27 String token = JWT.sign(login, 60L* 1000L* 30L);
28 Map<String,Object> result =new HashMap<String,Object>();
29 result.put("loginToken", token);
30 result.put("userId", user.getId());
31 result.put("user", user);
32
33 //保存用户信息到session
34 //session.setAttribute(user.getId() + "@@" + token, user);
35 //重建用户信息
36 this.rebuildLoginUser(user.getId(), token);
37 return ResponseCode.buildReturnMap(ResponseCode.RESPONSE_CODE_LOGIN_SUCCESS, result);
38 }
39
40 return ResponseCode.buildReturnMap(ResponseCode.USER_LOGIN_PWD_ERROR, false);
41 }
42
- 测试sso单点登录:
返回结果集:
Java代码
- {
"message":
"用户登录成功",
"data": {
"loginToken":
"eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJleHAiOjE1MDkzODA1OTU0NTksInBheWxvYWQiOiJ7XCJ1aWRcIjpcIjExXCIsXCJsb2dpbk5hbWVcIjpcImFkbWluXCIsXCJwYXNzd29yZFwiOlwiZjU0NGQxM2QyY2EwNDU5ZGQ0ZTU1NzVjNmZkYWIzMzM0MzE1MWFlZjgwYmE5ZTNiN2U1ZjM2MzJcIn0ifQ.56L60WtxHXSu9vNs6XsWy5zbmc3kP_IWG1YpReK50DM",
"userId":
"11",
"user": {
"QQ":
"2147775633",
"id":
"11",
"isNewRecord":
false,
"remarks":
"",
"createDate":
"2017-08-08 08:08:08",
"updateDate":
"2017-10-29 11:23:50",
"loginName":
"admin",
"no":
"00012",
"name":
"admin",
"email":
"2147775633@qq.com",
"phone":
"400000000",
"mobile":
"13888888888",
"userType":
"",
"loginIp":
"0:0:0:0:0:0:0:1",
"loginDate":
"2017-10-30 10:48:06",
"loginFlag":
"1",
"photo":
"",
"idCard":
"420888888888888888",
"oldLoginIp":
"0:0:0:0:0:0:0:1",
"oldLoginDate":
"2017-10-30 10:48:06",
"roleNames":
"",
"admin":
false
- }
- },
"code":
200
- }
愿意了解框架技术或者源码的朋友直接求求交流分享技术:3133806896
分布式的一些解决方案,有愿意了解的朋友可以找我们团队探讨
更多详细源码参考来源