E-commerce platform source code please add penguin beg: 3536247259. In distributed environment, how to support multi-terminal session sharing such as PC and APP (ios and Android) is also a solution that all companies need. I think it is out of date to solve the problem by using the traditional session method. Can we find a general solution? For example, using traditional CAS for SSO sso between multiple systems or using oAUth’s third-party login scheme? Today, we will briefly explain the use of Spring Interceptor mechanism, JWT authentication mode, Redis distributed cache sso sso, without further discussion, directly record the steps to share with you:
- Introduce the related JAR packages of JWT into the project pom.xml:
<dependency> <groupId>com.auth0</groupId> <artifactId> Java -jwt</artifactId> <version>2.2.0</version> </dependency>Copy the code
- Interceptor configuration:
<mvc:interceptor>
<mvc:mapping path="${adminPath}/ * *" />
<mvc:exclude-mapping path="${adminPath}/rest/login"/>
<bean class="com.ml.honghu.interceptor.LoginInterceptor" />
</mvc:interceptor>
Copy the code
I have simply configured the URLS to be blocked and the urls to be filtered (this depends on your own project).
- Write JWT encryption or decryption tool class:
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 = 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) {
returnnull; 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) {
returnnull; }}}Copy the code
This encryption tool class is I found from the Internet, if you want to modify, you can modify according to their own business.
- Create login. Java object for JWT encryption or decryption:
public class Login implements Serializable{ /** * */ private static final long serialVersionUID = 1899232511233819216L; /** * user id */ private String uid; /** * loginName */ private String loginName; /** * private String password; publicLogin(){
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; }}Copy the code
- Define the RedisLogin object used to store user objects to Redis using uid:
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; }}Copy the code
- Write the LoginInterceptor. Java interceptor
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 does not existif(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); // Determine whether the loginId after decrypting the token is the same as the loginId sent by the userif(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; } // Verify login time 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; } // System time > Validity period (indicates that the validity period has expired)if (System.currentTimeMillis() > redisLogin.getRefTime()) {
writer = response.getWriter();
ResponseVO responseVO = LoginResponseCode.buildEnumResponseVO(LoginResponseCode.LOGIN_TIME_EXP, false);
responseMessage(response, writer, responseVO);
return false; } // Refresh the validity period 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(); }}Copy the code
- Define the LoginResponseCode for the exception
public enum LoginResponseCode {
USERID_NOT_NULL(3001,"User ID cannot be empty."),
LOGIN_TOKEN_NOT_NULL(3002,"Login token cannot be empty."),
USERID_NOT_UNAUTHORIZED(3003, "User token or ID authentication failed"),
RESPONSE_CODE_UNLOGIN_ERROR(421, "No login exception"),
LOGIN_TIME_EXP(3004, "Login time is too long. Please log in again."); Private int code; // Status code private String message; Private LoginResponseCode(int code,String message) {this.code = code; this.message = message; } public intgetCode() {
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);
returnmap; }}Copy the code
- Write a unified SSO single sign-on interface:
@RequestMapping(value = "/login", method = RequestMethod.POST)
public Map<String, Object> login(@RequestBody JSONObject json){
String loginName = json.optString("loginName");
String password = json.optString("password"); // Verify user name cannot be emptyif(StringUtils.isEmpty(loginName)){
returnMemberResponseCode.buildReturnMap(MemberResponseCode.RESPONSE_CODE_USER_NAME_IS_NOT_EMPTY, null); } // Verify user password cannot be emptyif(StringUtils.isEmpty(password)){
returnMemberResponseCode.buildReturnMap(MemberResponseCode.RESPONSE_CODE_PWD_CAN_NOT_BE_EMPTY, null); } / / based on User name query the database User information User User. = systemService getBaseUserByLoginName (loginName); // The user name or password is incorrectif(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()); 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); // Save user information to session // session.setattribute (user.getid () +"@ @"+ token, user); This.rebuildloginuser (user.getid (), token); this.rebuildLoginUser(user.getid (), token);return ResponseCode.buildReturnMap(ResponseCode.RESPONSE_CODE_LOGIN_SUCCESS, result);
}
return ResponseCode.buildReturnMap(ResponseCode.USER_LOGIN_PWD_ERROR, false);
}
Copy the code
- Testing SSO sso:
Return result set:
{
"message": "User logged in successfully"."data": {
"loginToken": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJleHAiOjE1MDkzODA1OTU0NTksInBheWxvYWQiOiJ7XCJ1aWRcIjpcIjExXCIsXCJsb2dpbk5hbWVcIj pcImFkbWluXCIsXCJwYXNzd29yZFwiOlwiZjU0NGQxM2QyY2EwNDU5ZGQ0ZTU1NzVjNmZkYWIzMzM0MzE1MWFlZjgwYmE5ZTNiN2U1ZjM2MzJcIn0ifQ.56L 60WtxHXSu9vNs6XsWy5zbmc3kP_IWG1YpReK50DM"."userId": "11"."user": {
"QQ":"2147775633"."id": "11"."isNewRecord": false."remarks": ""."createDate": "The 2017-08-08 08:08:08"."updateDate": "The 2017-10-29 11:23:50"."loginName": "admin"."no": "00012"."name": "admin"."email": "[email protected]"."phone": "400000000"."mobile": "13888888888"."userType": ""."loginIp": "0:0:0:0:0:0:0:1"."loginDate": "The 2017-10-30 10:48:06"."loginFlag": "1"."photo": ""."idCard": "420888888888888888"."oldLoginIp": "0:0:0:0:0:0:0:1"."oldLoginDate": "The 2017-10-30 10:48:06"."roleNames": ""."admin": false}},"code": 200}Copy the code
That’s it!!