Browse Source

登录接口优化

wangmh 7 years ago
parent
commit
ef52df01be

+ 23 - 220
sso-server/src/main/java/com/uas/sso/controller/LoginController.java

@@ -4,10 +4,11 @@ import com.alibaba.fastjson.JSON;
 import com.alibaba.fastjson.JSONObject;
 import com.uas.account.AccountConfig;
 import com.uas.sso.*;
-import com.uas.sso.exception.VisibleError;
-import com.uas.sso.foreign.factory.ForeignFactory;
-import com.uas.sso.foreign.entity.ForeignInfo;
-import com.uas.sso.foreign.service.ForeignService;
+import com.uas.sso.entity.UserAccount;
+import com.uas.sso.entity.login.ForeignLogin;
+import com.uas.sso.entity.login.PasswordLogin;
+import com.uas.sso.entity.login.SmsLogin;
+import com.uas.sso.entity.login.TokenLogin;
 import com.uas.sso.foreign.bihe.entity.BiHeInfo;
 import com.uas.sso.foreign.bihe.service.BiHeService;
 import com.uas.sso.common.util.HttpUtil;
@@ -16,6 +17,7 @@ import com.uas.sso.entity.*;
 import com.uas.sso.entity.Token;
 import com.uas.sso.service.*;
 import com.uas.sso.util.*;
+import com.uas.sso.util.BeanUtil;
 import com.uas.sso.web.waf.request.WafRequestWrapper;
 import com.uas.sso.foreign.weixin.entity.OAuthInfo;
 import com.uas.sso.foreign.weixin.service.WeChatService;
@@ -84,80 +86,13 @@ public class LoginController extends BaseController {
     @Autowired
     private BiHeService biHeService;
 
-    @RequestMapping(method = RequestMethod.POST)
-    public ModelMap login() {
-        // 获取登录信息
-        Long start = System.currentTimeMillis();
-        request.getSession().setAttribute("time", start);
-        WafRequestWrapper wr = new WafRequestWrapper(request);
-        String appId = wr.getParameter("appId");
-        String spaceUU = wr.getParameter("spaceUU");
-        String username = StringUtils.trimAllWhitespace(wr.getParameter("username"));
-        String password = wr.getParameter("password");
-        String captcha = wr.getParameter("captcha");
-        String returnUrl = wr.getParameter("returnUrl");
-        String baseUrl = wr.getParameter("baseUrl");
-
-        // 校验空参数
-        try {
-            Assert.hasText(username, "用户名不能为空");
-            Assert.hasText(password, "密码不能为空");
-        } catch (IllegalArgumentException e) {
-            return error(e.getMessage());
-        }
-
-        // 设置baseUrl
-        if (!StringUtils.isEmpty(baseUrl)) {
-            request.getSession().setAttribute("baseUrl", baseUrl);
-        }
-
-        // 校验appId,appId为空的话默认为sso
-        appId = StringUtils.isEmpty(appId) ? SSOHelper.getSSOService().getConfig().getAppName() : appId;
-        App app = appService.findOne(appId);
-        if (app == null) {
-            return error("应用id不存在");
-        }
-
-        // 校验returnUrl,为空默认为优软云
-        if (StringUtils.isEmpty(returnUrl)) {
-            returnUrl = HOME_PAGE;
-        }
-        // 获取用户基本信息
-        User user = userService.findByUsername(username);
-        if (user == null) {
-            return error("用户名或密码错误");
-        }
-
-        // 校验账户密码输错次数
-        UserRecord userRecord = userRecordService.findOne(user.getUserUU());
-        int pwdErrorCount = userRecord == null ? 0 : userRecord.getPwdErrorCount();
-        Object loginCaptcha = request.getSession().getAttribute(LOGIN_CAPTCHA);
-        String checkCode = loginCaptcha == null ? "" : loginCaptcha.toString();
-        if (pwdErrorCount >= PWD_ERROR_FIVE_TIME) {
-            return error("403", "密码错误次数已达上限,今日无法登陆");
-        }
-        // 校验账号是否被锁定,5次输错密码
-        if (pwdErrorCount >= PWD_ERROR_THREE_TIME && StringUtils.isEmpty(captcha)) {
-            return error("404", "验证码不能为空");
-        }
-        if (pwdErrorCount >= PWD_ERROR_THREE_TIME && !captcha.equalsIgnoreCase(checkCode)) {
-            return error("验证码错误");
-        }
-
-        // 校验密码
-        String encryPwd = userService.getEncryPassword(Const.ENCRY_FORMAT, password, user.getSalt());
-        if (!encryPwd.equals(user.getPassword())) {
-            pwdErrorCount = inputErrorPwd(user.getUserUU());
-            return error("您输入的账号或密码有误").addAttribute("errorCount", pwdErrorCount);
-        }
+    @Autowired
+    private LoginService loginService;
 
-        // 校验密码强度,如果和存储的不同,则保存
-        int strength = PasswordLevelUtils.checkPasswordLevel(password).getValue();
-        if (strength != user.getPasswordLevel()) {
-            user.setPasswordLevel(strength);
-            userService.save(user);
-        }
-        return success(login(user.getUserUU(), appId, spaceUU, returnUrl));
+    @RequestMapping(method = RequestMethod.POST)
+    public ModelMap login(PasswordLogin loginParam) {
+        loginParam.setSureCaptcha((String) request.getSession().getAttribute(LOGIN_CAPTCHA));
+        return success(loginService.loginByPassword(loginParam));
     }
 
     /**
@@ -228,80 +163,22 @@ public class LoginController extends BaseController {
      * erp和uu互联跳转
      * 代理登录,根据tokenId拿到当前用户登录的用户uu号和企业uu号进行登录
      *
-     * @param token tokenId
-     * @param appId 应用id
-     * @param returnUrl 跳转页面
-     * @param baseUrl 而外登录接口
+     * @param loginParam loginParam
      * @return
      */
     @RequestMapping(value = "/proxy", method = RequestMethod.POST)
-    public ModelMap loginProxyByToken(String token, String appId, String returnUrl, String baseUrl) {
-        Token tk = tokenService.findOne(token);
-        if (null != tk) {
-            JSONObject data = JSON.parseObject(JSON.toJSONString(tk.getBind()));
-            Long userUU = data.getLong("userUU");
-            Long spaceUU = data.getLong("spaceUU");
-            request.getSession().setAttribute("baseUrl", baseUrl);
-            App app = appService.findOne(appId);
-            if (app != null) {
-                app = StringUtils.isEmpty(app.getUserControl()) ? app : appService.findOne(app.getUserControl());
-            }
-
-            if (StringUtils.isEmpty(returnUrl)) {
-                returnUrl = HOME_PAGE;
-            }
-
-            if (app == null) {
-                app = appService.findOne(AccountConfig.ACCOUNT_CENTER);
-            }
-
-            UserAccount userAccount = userAccountService.findOneByUserUU(app.getUid(), userUU, spaceUU);
-
-            if (userAccount == null) {
-                return success(new ModelMap("returnUrl", HttpUtil.decodeURL(returnUrl)));
-            }
-            return success(loginByUser(userAccount, returnUrl, true));
-        }
-        return success(new ModelMap("returnUrl", HttpUtil.decodeURL(returnUrl)));
+    public ModelMap loginProxyByToken(TokenLogin loginParam) {
+        return success(loginService.loginByToken(loginParam));
     }
 
     /**
      * uu互联代理登录
-     * @param token tokenId
-     * @param appId 登录应用应用id
-     * @param spaceUU 企业uu号
-     * @param returnUrl 跳转页面
+     * @param loginParam loginParam
      * @return
      */
     @RequestMapping(value = "/mobile/proxy", method = RequestMethod.POST)
-    public ModelMap loginProxyByToken(String token, @RequestParam(defaultValue = "sso") String appId, Long spaceUU, String returnUrl, String baseUrl) {
-        Token tk = tokenService.findOne(token);
-        if (tk == null) {
-            return success(new ModelMap("returnUrl", HttpUtil.decodeURL(returnUrl)));
-        }
-        App app = appService.findOne(appId);
-        baseUrl = StringUtils.isEmpty(baseUrl) ? app.getLoginUrl() : baseUrl;
-        request.getSession().setAttribute("baseUrl", baseUrl);
-        ModelMap modelMap = (ModelMap) tk.getBind();
-        Long userUU = (Long) modelMap.get("userUU");
-        if (modelMap.containsKey("spaceUU")) {
-            spaceUU = (Long) modelMap.get("spaceUU");
-        }
-
-        if (app != null) {
-            app = StringUtils.isEmpty(app.getUserControl()) ? app : appService.findOne(app.getUserControl());
-        }
-
-        if (app == null) {
-            app = appService.findOne(AccountConfig.ACCOUNT_CENTER);
-        }
-
-        UserAccount userAccount = userAccountService.findOneByUserUU(app.getUid(), userUU, spaceUU);
-        if (userAccount == null) {
-            List<UserAccount> userAccounts = userAccountService.findByUserUU(app.getUid(), userUU);
-            return success(getSpaceSelect(userAccounts, false));
-        }
-        return success(loginByUser(userAccount, returnUrl, false));
+    public ModelMap loginProxyByTokenMobile(TokenLogin loginParam) {
+        return success(loginService.loginByToken(loginParam));
     }
 
     /**
@@ -655,51 +532,8 @@ public class LoginController extends BaseController {
      * @return
      */
     @RequestMapping(value = "/sms", method = RequestMethod.POST)
-    public ModelMap loginBySms(String code, String token) {
-        // 获取登录信息
-        WafRequestWrapper wr = new WafRequestWrapper(request);
-        String appId = wr.getParameter("appId");
-        String spaceUU = wr.getParameter("spaceUU");
-        String mobile = StringUtils.trimAllWhitespace(wr.getParameter("mobile"));
-        String returnUrl = wr.getParameter("returnUrl");
-        String baseUrl = wr.getParameter("baseUrl");
-
-        appId = StringUtils.isEmpty(appId) ? AccountConfig.ACCOUNT_CENTER : appId;
-
-        // 校验手机号是否被注册
-        boolean hasRegister = userService.mobileHasRegistered(mobile);
-        if (!hasRegister) {
-            return error("该手机号未注册,请先注册");
-        }
-
-        // 设置baseUrl
-        if (!StringUtils.isEmpty(baseUrl)) {
-            request.getSession().setAttribute("baseUrl", baseUrl);
-        }
-
-        if (StringUtils.isEmpty(returnUrl)) {
-            returnUrl = HOME_PAGE;
-        }
-
-        // 校验token
-        Assert.hasText(token, "请先获取验证码");
-        Token existToken = tokenService.findOne(token);
-        if (existToken == null || existToken.isExpired()) {
-            return error("验证码已过期,请重新获取");
-        }
-        if (!StringUtils.isEmpty(existToken.getMobile()) && !existToken.getMobile().equals(mobile)) {
-            return error("手机号被修改,请重新获取验证码");
-        }
-        if (StringUtils.isEmpty(code) || !code.equals(existToken.getBind())) {
-            return error("验证码错误");
-        }
-
-        // 获取登录用户
-        User user = userService.findByMobile(mobile);
-        if (user == null) {
-            return error("该手机号未注册");
-        }
-        return success(login(user.getUserUU(), appId, spaceUU, returnUrl));
+    public ModelMap loginBySms(SmsLogin loginParam) {
+        return success(loginService.loginBySms(loginParam));
     }
 
     /**
@@ -853,44 +687,13 @@ public class LoginController extends BaseController {
         return success(login(user.getUserUU(), appId, spaceUU, returnUrl));
     }
 
-
     /**
      * 碧合登录接口
-     * @param appId 应用id(优软云应用id)
-     * @param code 第三方获取用户信息code
+     * @param loginParam
      * @return
      */
     @RequestMapping(value = "/foreignLogin", method = RequestMethod.POST)
-    public ModelMap foreignLogin(@RequestParam(defaultValue = "city") String appId, String code, String type) {
-        // 获取用户信息
-        User user = null;
-        Long userUU = (Long) request.getSession().getAttribute("userUU");
-        if (userUU != null) {
-            user = new User(userUU);
-        } else {
-            ForeignService foreignService = ForeignFactory.getForeignService(type);
-            ForeignInfo foreignInfo = foreignService.getForeignInfoByCode(code);
-            String accessToken = Optional.ofNullable(foreignInfo).map(ForeignInfo::getForeignAccessToken).orElseThrow(() -> new VisibleError("验证信息过期"));
-            user = userService.findByForeignId(foreignInfo);
-            // user为空提示未注册,不为空则放入session绑定用户使用
-            if (user == null) {
-                // 提示前端用户微信未绑定账号
-                ModelMap map = new ModelMap("data", foreignInfo);
-                Token token = new Token(map, foreignInfo.getForeignExpiresIn());
-                tokenService.save(token);
-                ModelMap data = new ModelMap("hasRegister", false);
-                data.put("token", token.getId());
-                return success(data);
-            }
-            request.getSession().setAttribute("userUU", user.getUserUU());
-        }
-
-        // 登录
-        WafRequestWrapper wr = new WafRequestWrapper(request);
-        String spaceUU = wr.getParameter("spaceUU");
-        String returnUrl = wr.getParameter("returnUrl");
-        String baseUrl = wr.getParameter("baseUrl");
-        request.getSession().setAttribute("baseUrl", baseUrl);
-        return success(login(user.getUserUU(), appId, spaceUU, returnUrl).addAttribute("hasRegister", true));
+    public ModelMap foreignLogin(ForeignLogin loginParam) {
+        return success(loginService.loginByForeign(loginParam));
     }
 }

+ 3 - 1
sso-server/src/main/java/com/uas/sso/core/Const.java

@@ -66,5 +66,7 @@ public class Const {
 
     public static final String ERROR = "error";
 
-    public static Long SPACEUU_PERSONAL = 1L;
+    public static final Long SPACEUU_PERSONAL = 1L;
+
+    public static final String HOME_PAGE = "http://www.ubtob.com";
 }

+ 52 - 0
sso-server/src/main/java/com/uas/sso/entity/login/BaseLogin.java

@@ -0,0 +1,52 @@
+package com.uas.sso.entity.login;
+
+import com.uas.sso.AccountConfig;
+import com.uas.sso.core.Const;
+
+/**
+ * @author wangmh
+ * @create 2018-08-09 13:47
+ * @desc 登录实体基类
+ **/
+public abstract class BaseLogin {
+
+    private String appId = AccountConfig.ACCOUNT_CENTER;
+
+    private String returnUrl = Const.HOME_PAGE;
+
+    private String baseUrl;
+
+    private boolean loginAll = true;
+
+    public String getAppId() {
+        return appId;
+    }
+
+    public void setAppId(String appId) {
+        this.appId = appId;
+    }
+
+    public String getReturnUrl() {
+        return returnUrl;
+    }
+
+    public void setReturnUrl(String returnUrl) {
+        this.returnUrl = returnUrl;
+    }
+
+    public String getBaseUrl() {
+        return baseUrl;
+    }
+
+    public void setBaseUrl(String baseUrl) {
+        this.baseUrl = baseUrl;
+    }
+
+    public boolean isLoginAll() {
+        return loginAll;
+    }
+
+    public void setLoginAll(boolean loginAll) {
+        this.loginAll = loginAll;
+    }
+}

+ 49 - 0
sso-server/src/main/java/com/uas/sso/entity/login/ForeignLogin.java

@@ -0,0 +1,49 @@
+package com.uas.sso.entity.login;
+
+/**
+ * @author wangmh
+ * @create 2018-08-13 9:29
+ * @desc
+ **/
+public class ForeignLogin extends BaseLogin {
+
+    private String code;
+
+    private String type;
+
+    private String state;
+
+    private Long spaceUU;
+
+    public String getCode() {
+        return code;
+    }
+
+    public void setCode(String code) {
+        this.code = code;
+    }
+
+    public String getType() {
+        return type;
+    }
+
+    public void setType(String type) {
+        this.type = type;
+    }
+
+    public String getState() {
+        return state;
+    }
+
+    public void setState(String state) {
+        this.state = state;
+    }
+
+    public Long getSpaceUU() {
+        return spaceUU;
+    }
+
+    public void setSpaceUU(Long spaceUU) {
+        this.spaceUU = spaceUU;
+    }
+}

+ 76 - 0
sso-server/src/main/java/com/uas/sso/entity/login/PasswordLogin.java

@@ -0,0 +1,76 @@
+package com.uas.sso.entity.login;
+
+import org.springframework.util.StringUtils;
+
+/**
+ * @author wangmh
+ * @create 2018-08-09 13:53
+ * @desc 账号密码登录实体
+ **/
+public class PasswordLogin extends BaseLogin {
+
+    /**
+     * 用户名
+     */
+    private String username;
+
+    /**
+     * 密码
+     */
+    private String password;
+
+    /**
+     * 企业uu号
+     */
+    private Long spaceUU;
+
+    /**
+     * 验证码
+     */
+    private String captcha;
+
+    /**
+     * 正确的验证码
+     */
+    private String sureCaptcha;
+
+    public String getUsername() {
+        return username;
+    }
+
+    public void setUsername(String username) {
+        this.username = StringUtils.trimAllWhitespace(username);
+    }
+
+    public String getPassword() {
+        return password;
+    }
+
+    public void setPassword(String password) {
+        this.password = password;
+    }
+
+    public Long getSpaceUU() {
+        return spaceUU;
+    }
+
+    public void setSpaceUU(Long spaceUU) {
+        this.spaceUU = spaceUU;
+    }
+
+    public String getCaptcha() {
+        return captcha;
+    }
+
+    public void setCaptcha(String captcha) {
+        this.captcha = captcha;
+    }
+
+    public String getSureCaptcha() {
+        return sureCaptcha;
+    }
+
+    public void setSureCaptcha(String sureCaptcha) {
+        this.sureCaptcha = sureCaptcha;
+    }
+}

+ 51 - 0
sso-server/src/main/java/com/uas/sso/entity/login/SmsLogin.java

@@ -0,0 +1,51 @@
+package com.uas.sso.entity.login;
+
+import org.springframework.util.StringUtils;
+
+/**
+ * @author wangmh
+ * @create 2018-08-10 18:00
+ * @desc
+ **/
+public class SmsLogin extends BaseLogin {
+
+    private String mobile;
+
+    private String code;
+
+    private String token;
+
+    private Long spaceUU;
+
+    public String getMobile() {
+        return mobile;
+    }
+
+    public void setMobile(String mobile) {
+        this.mobile = StringUtils.trimAllWhitespace(mobile);
+    }
+
+    public String getCode() {
+        return code;
+    }
+
+    public void setCode(String code) {
+        this.code = code;
+    }
+
+    public String getToken() {
+        return token;
+    }
+
+    public void setToken(String token) {
+        this.token = token;
+    }
+
+    public Long getSpaceUU() {
+        return spaceUU;
+    }
+
+    public void setSpaceUU(Long spaceUU) {
+        this.spaceUU = spaceUU;
+    }
+}

+ 29 - 0
sso-server/src/main/java/com/uas/sso/entity/login/TokenLogin.java

@@ -0,0 +1,29 @@
+package com.uas.sso.entity.login;
+
+/**
+ * @author wangmh
+ * @create 2018-08-10 16:35
+ * @desc
+ **/
+public class TokenLogin extends BaseLogin {
+
+    private String token;
+
+    private Long spaceUU;
+
+    public String getToken() {
+        return token;
+    }
+
+    public void setToken(String token) {
+        this.token = token;
+    }
+
+    public Long getSpaceUU() {
+        return spaceUU;
+    }
+
+    public void setSpaceUU(Long spaceUU) {
+        this.spaceUU = spaceUU;
+    }
+}

+ 43 - 0
sso-server/src/main/java/com/uas/sso/service/LoginService.java

@@ -0,0 +1,43 @@
+package com.uas.sso.service;
+
+import com.uas.sso.entity.login.ForeignLogin;
+import com.uas.sso.entity.login.PasswordLogin;
+import com.uas.sso.entity.login.SmsLogin;
+import com.uas.sso.entity.login.TokenLogin;
+import org.springframework.ui.ModelMap;
+
+/**
+ * @author wangmh
+ * @create 2018-08-10 10:19
+ * @desc
+ **/
+public interface LoginService {
+
+    /**
+     * 根据密码返回登录
+     * @param loginParam
+     * @return
+     */
+    ModelMap loginByPassword(PasswordLogin loginParam);
+
+    /**
+     * 通过token登录
+     * @param loginParam
+     * @return
+     */
+    ModelMap loginByToken(TokenLogin loginParam);
+
+    /**
+     * 通过短信验证码登录
+     * @param loginParam
+     * @return
+     */
+    ModelMap loginBySms(SmsLogin loginParam);
+
+    /**
+     * 通过第三方登录
+     * @param loginParam
+     * @return
+     */
+    ModelMap loginByForeign(ForeignLogin loginParam);
+}

+ 317 - 0
sso-server/src/main/java/com/uas/sso/service/impl/LoginServiceImpl.java

@@ -0,0 +1,317 @@
+package com.uas.sso.service.impl;
+
+import com.alibaba.fastjson.JSON;
+import com.alibaba.fastjson.JSONObject;
+import com.uas.sso.SSOConfig;
+import com.uas.sso.SSOHelper;
+import com.uas.sso.SSOToken;
+import com.uas.sso.common.util.HttpUtil;
+import com.uas.sso.core.Const;
+import com.uas.sso.entity.App;
+import com.uas.sso.entity.login.*;
+import com.uas.sso.entity.Token;
+import com.uas.sso.entity.User;
+import com.uas.sso.entity.UserAccount;
+import com.uas.sso.exception.VisibleError;
+import com.uas.sso.foreign.entity.ForeignInfo;
+import com.uas.sso.foreign.factory.ForeignFactory;
+import com.uas.sso.foreign.service.ForeignService;
+import com.uas.sso.service.AppService;
+import com.uas.sso.service.LoginService;
+import com.uas.sso.service.PersonalAccountService;
+import com.uas.sso.service.TokenService;
+import com.uas.sso.service.UserAccountService;
+import com.uas.sso.service.UserService;
+import com.uas.sso.util.PasswordLevelUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import org.springframework.ui.ModelMap;
+import org.springframework.util.CollectionUtils;
+import org.springframework.util.StringUtils;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Optional;
+
+/**
+ * @author wangmh
+ * @create 2018-08-10 10:19
+ * @desc
+ **/
+@Service
+public class LoginServiceImpl implements LoginService {
+
+    @Autowired
+    private UserService userService;
+
+    @Autowired
+    private TokenService tokenService;
+
+    @Autowired
+    private AppService appService;
+
+    @Autowired
+    private UserAccountService userAccountService;
+
+    @Autowired
+    private PersonalAccountService personalAccountService;
+
+    @Autowired
+    protected HttpServletRequest request;
+
+    @Autowired
+    protected HttpServletResponse response;
+    /**
+     * 密码输错3次
+     */
+    private static final int PWD_ERROR_FIVE_TIME = 5;
+
+    /**
+     * 密码输错3次
+     */
+    private static final int PWD_ERROR_THREE_TIME = 3;
+
+    @Override
+    public ModelMap loginByPassword(PasswordLogin loginParam) {
+        // 校验参数
+        if (loginParam == null) {
+            throw new VisibleError("参数错误");
+        }
+        if (loginParam.getUsername() == null) {
+            throw new VisibleError("用户名不能为空");
+        }
+        if (loginParam.getPassword() == null) {
+            throw new VisibleError("密码不能为空");
+        }
+
+        // 获取用户信息
+        User user = userService.findByUsername(loginParam.getUsername());
+        if (user == null) {
+            throw new VisibleError("用户名或密码错误");
+        }
+
+        // 获取密码错误次数
+        Integer pwdErrorCount = getPwdErrorCount(user);
+
+        // 校验验证码
+        if (pwdErrorCount >= PWD_ERROR_FIVE_TIME) {
+            throw new VisibleError( "密码错误次数已达上限,今日无法登陆");
+        }
+        // 校验账号是否被锁定,5次输错密码
+        if (pwdErrorCount >= PWD_ERROR_THREE_TIME && StringUtils.isEmpty(loginParam.getSureCaptcha())) {
+            throw new VisibleError("验证码不能为空");
+        }
+        if (pwdErrorCount >= PWD_ERROR_THREE_TIME && !loginParam.getSureCaptcha().equalsIgnoreCase(loginParam.getCaptcha())) {
+            throw new VisibleError("验证码错误");
+        }
+
+        // 校验密码
+        userService.checkPassword(user.getUserUU(), loginParam.getPassword(), false);
+
+        // 校验密码强度,如果和存储的不同,则保存
+        int strength = PasswordLevelUtils.checkPasswordLevel(loginParam.getPassword()).getValue();
+        if (strength != user.getPasswordLevel()) {
+            user.setPasswordLevel(strength);
+            userService.save(user);
+        }
+
+        // 登录
+        return login(user.getUserUU(), loginParam.getSpaceUU(), loginParam);
+    }
+
+    @Override
+    public ModelMap loginByToken(TokenLogin loginParam) {
+        Token tk = tokenService.findOne(loginParam.getToken());
+        // token不存在则不登录返回
+        if (tk == null) {
+            new ModelMap("returnUrl", HttpUtil.decodeURL(loginParam.getReturnUrl()));
+        }
+
+        JSONObject data = JSON.parseObject(JSON.toJSONString(tk.getBind()));
+        Long userUU = data.getLong("userUU");
+        Long spaceUU = data.getLong("spaceUU");
+        if (spaceUU == null) {
+            spaceUU = loginParam.getSpaceUU();
+        }
+
+        return login(userUU, spaceUU, loginParam);
+    }
+
+    @Override
+    public ModelMap loginBySms(SmsLogin loginParam) {
+        String token = loginParam.getToken();
+        String code = loginParam.getCode();
+        String mobile = loginParam.getMobile();
+
+        // 校验token
+        if (token == null) {
+            throw new VisibleError("请先获取验证码");
+        }
+        Token existToken = tokenService.findOne(token);
+        if (existToken == null || existToken.isExpired()) {
+            throw new VisibleError("验证码已过期,请重新获取");
+        }
+        if (!StringUtils.isEmpty(existToken.getMobile()) && !existToken.getMobile().equals(mobile)) {
+            throw new VisibleError("手机号被修改,请重新获取验证码");
+        }
+        if (StringUtils.isEmpty(code) || !code.equals(existToken.getBind())) {
+            throw new VisibleError("验证码错误");
+        }
+
+        // 获取登录用户
+        User user = userService.findByMobile(mobile);
+        if (user == null) {
+            throw new VisibleError("该手机号未注册");
+        }
+        return login(user.getUserUU(), loginParam.getSpaceUU(), loginParam);
+    }
+
+    @Override
+    public ModelMap loginByForeign(ForeignLogin loginParam) {
+        String code = loginParam.getCode();
+        String type = loginParam.getType();
+        Long spaceUU = loginParam.getSpaceUU();
+
+        // 获取用户信息
+        User user = null;
+        Long userUU = (Long) request.getSession().getAttribute("userUU");
+        if (userUU != null) {
+            user = new User(userUU);
+        } else {
+            ForeignService foreignService = ForeignFactory.getForeignService(type);
+            ForeignInfo foreignInfo = foreignService.getForeignInfoByCode(code);
+            Optional<String> accessTokenOptional = Optional.ofNullable(foreignInfo).map(ForeignInfo::getForeignAccessToken);
+            if (accessTokenOptional.isPresent()) {
+                throw new VisibleError("验证信息过期");
+            }
+
+            user = userService.findByForeignId(foreignInfo);
+            // user为空提示未注册,不为空则放入session绑定用户使用
+            if (user == null) {
+                // 提示前端用户微信未绑定账号
+                ModelMap map = new ModelMap("data", foreignInfo);
+                Token token = new Token(map, foreignInfo.getForeignExpiresIn());
+                tokenService.save(token);
+                ModelMap data = new ModelMap("hasRegister", false);
+                data.put("token", token.getId());
+                return data;
+            }
+            request.getSession().setAttribute("userUU", user.getUserUU());
+        }
+
+        return login(user.getUserUU(), spaceUU, loginParam).addAttribute("hasRegister", true);
+    }
+
+    private ModelMap login(Long userUU, Long spaceUU, BaseLogin loginParam) {
+        App app = appService.findOne(loginParam.getAppId());
+        if (app == null) {
+            throw new VerifyError("应用不存在");
+        }
+        App controlApp = StringUtils.isEmpty(app.getUserControl()) ? app : appService.findOne(app.getUserControl());
+        boolean personalEnable = Const.YES == controlApp.getPersonalEnable();
+
+        UserAccount userAccount = null;
+        if (spaceUU == null) {
+            // 找到用户账号信息
+            List<UserAccount> userAccounts = userAccountService.findByUserUU(controlApp.getUid(), userUU);
+
+            // 没有记录
+            if (CollectionUtils.isEmpty(userAccounts)) {
+                // 没有记录如果当前应用允许个人账号的话,查找个人账号
+                userAccount = personalAccountService.findOneByUserUU(controlApp.getUid(), userUU);
+                if (!personalEnable) {
+                    // 不支持个人账号则跳转优软云
+                    loginParam.setReturnUrl(Const.HOME_PAGE);
+                }
+            } else if (userAccounts.size() == 1) {
+                // 应用允许个人账号,并且账号未绑定企业,或者只绑定了一个企业,直接登录
+                userAccount = userAccounts.get(0);
+            } else {
+                // 返回企业id和名称
+                return getSpaceSelect(userAccounts, personalEnable);
+            }
+        } else if (personalEnable && Long.valueOf(spaceUU).equals(Const.SPACEUU_PERSONAL)) {
+            // 使用个人账号登录
+           userAccount = personalAccountService.findOneByUserUU(controlApp.getUid(), userUU);
+        } else {
+            // 带企业登录
+            userAccount = userAccountService.findOneByUserUU(controlApp.getUid(), userUU, Long.valueOf(spaceUU));
+        }
+
+        // 可能用户不在该企业,可能企业未开通该应用
+        if (userAccount == null) {
+            throw new VisibleError("数据错误");
+        }
+
+        // 设置cookie
+        SSOToken st = new SSOToken(request, userAccount.getMobile());
+        st.setData(JSON.toJSONString(userAccount));
+        SSOHelper.setSSOCookie(request, response, st, true);
+        return loginByUser(userAccount, loginParam);
+    }
+
+    private ModelMap getSpaceSelect(List<UserAccount> userAccounts, boolean personalEnable) {
+        List<Map<String, Object>> spaces = new ArrayList<Map<String, Object>>();
+        Map<String, Object> space = null;
+        // 设置带企业账号
+        for (UserAccount userAccount : userAccounts) {
+            space = new HashMap<String, Object>(2);
+            space.put("id", userAccount.getSpaceUU());
+            space.put("name", userAccount.getSpaceName());
+            spaces.add(space);
+        }
+
+        // 设置个人账号
+        if (personalEnable) {
+            space = new HashMap<String, Object>(2);
+            space.put("id", Const.SPACEUU_PERSONAL);
+            space.put("name", String.format("%s(个人)", userAccounts.get(0).getVipName()));
+            spaces.add(space);
+        }
+        return new ModelMap("spaces", spaces);
+    }
+
+    private ModelMap loginByUser(UserAccount userAccount, BaseLogin loginParam) {
+        resetPwdCount(userAccount.getUserUU());
+
+        // 设置返回值,通知各个应用用户已经登录
+        ModelMap data = new ModelMap();
+        data = addOtherAppRequestData(userAccount, data, loginParam);
+        data.put("returnUrl", HttpUtil.decodeURL(loginParam.getReturnUrl()));
+        return data;
+    }
+
+    private void resetPwdCount(Long userUU) {
+        tokenService.delete("login_count_" + userUU);
+    }
+
+    private ModelMap addOtherAppRequestData(UserAccount userAccount, ModelMap data, BaseLogin loginParam) {
+        List<String> loginUrls = appService.findAllLoginUrl();
+        boolean loginAll = loginParam.isLoginAll();
+        String currentUrl = HttpUtil.decodeURL(loginParam.getBaseUrl());
+
+        // 添加baseUrl
+        if (loginAll && !loginUrls.contains(currentUrl)) {
+            loginUrls.add(currentUrl);
+        }
+
+        data.put("loginUrls", loginUrls);
+        data.put("currentUrl", currentUrl);
+
+        // 添加传递数据
+        JSONObject jsonObject = JSON.parseObject(JSON.toJSONString(userAccount));
+        Integer maxage = (Integer) request.getAttribute(SSOConfig.SSO_COOKIE_MAXAGE);
+        jsonObject.put("maxage", maxage);
+        data.put("data", jsonObject);
+        return data;
+    }
+
+    private Integer getPwdErrorCount(User user) {
+        Token token = tokenService.findOne("login_count_" + user.getUserUU());
+        return (Integer) Optional.ofNullable(token).map(Token::getBind).orElse(0);
+    }
+}

+ 6 - 0
sso-server/src/main/resources/spring/ehcache.xml

@@ -33,4 +33,10 @@
            maxElementsInMemory="10000" eternal="false" overflowToDisk="false"
            memoryStoreEvictionPolicy="LFU" timeToIdleSeconds="604800"
            timeToLiveSeconds="604800" />
+
+    <!-- 消息服务配置缓存 -->
+    <cache name="AppCache"
+           maxElementsInMemory="10000" eternal="false" overflowToDisk="false"
+           memoryStoreEvictionPolicy="LFU" timeToIdleSeconds="1800"
+           timeToLiveSeconds="14400" />
 </ehcache>