LoginController.java 31 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827
  1. package com.uas.sso.controller;
  2. import com.alibaba.fastjson.JSON;
  3. import com.alibaba.fastjson.JSONObject;
  4. import com.uas.account.AccountConfig;
  5. import com.uas.account.entity.UserDetail;
  6. import com.uas.sso.*;
  7. import com.uas.sso.common.util.HttpUtil;
  8. import com.uas.sso.core.Const;
  9. import com.uas.sso.entity.*;
  10. import com.uas.sso.entity.Token;
  11. import com.uas.sso.service.*;
  12. import com.uas.sso.util.*;
  13. import com.uas.sso.web.waf.request.WafRequestWrapper;
  14. import com.uas.sso.weixin.service.WeChatService;
  15. import org.springframework.beans.factory.annotation.Autowired;
  16. import org.springframework.ui.ModelMap;
  17. import org.springframework.util.Assert;
  18. import org.springframework.util.CollectionUtils;
  19. import org.springframework.util.StringUtils;
  20. import org.springframework.web.bind.annotation.*;
  21. import org.springframework.web.servlet.ModelAndView;
  22. import java.io.IOException;
  23. import java.util.*;
  24. /**
  25. * 登录controller
  26. *
  27. * @author wangmh
  28. * @date 2018/1/5
  29. */
  30. @RequestMapping("/sso/login")
  31. @RestController
  32. public class LoginController extends BaseController {
  33. /**
  34. * 密码输错3次
  35. */
  36. private static final int PWD_ERROR_FIVE_TIME = 5;
  37. /**
  38. * 密码输错3次
  39. */
  40. private static final int PWD_ERROR_THREE_TIME = 3;
  41. /**
  42. * 登录验证码存session的key值
  43. */
  44. private static final String LOGIN_CAPTCHA = "loginCaptcha";
  45. /**
  46. * 优软云首页地址
  47. */
  48. private static final String HOME_PAGE = "https://www.ubtob.com/";
  49. @Autowired
  50. private AppService appService;
  51. @Autowired
  52. private UserService userService;
  53. @Autowired
  54. private UserspaceService userspaceService;
  55. @Autowired
  56. private UserAccountService userAccountService;
  57. @Autowired
  58. private PersonalAccountService personalAccountService;
  59. @Autowired
  60. private WeChatService weChatService;
  61. @RequestMapping(method = RequestMethod.POST)
  62. public ModelMap login() {
  63. // 获取登录信息
  64. WafRequestWrapper wr = new WafRequestWrapper(request);
  65. String appId = wr.getParameter("appId");
  66. String spaceUU = wr.getParameter("spaceUU");
  67. String username = StringUtils.trimAllWhitespace(wr.getParameter("username"));
  68. String password = wr.getParameter("password");
  69. String captcha = wr.getParameter("captcha");
  70. String returnUrl = wr.getParameter("returnUrl");
  71. String baseUrl = wr.getParameter("baseUrl");
  72. // 校验空参数
  73. try {
  74. Assert.hasText(username, "用户名不能为空");
  75. Assert.hasText(password, "密码不能为空");
  76. } catch (IllegalArgumentException e) {
  77. return error(e.getMessage());
  78. }
  79. // 设置baseUrl
  80. if (!StringUtils.isEmpty(baseUrl)) {
  81. request.getSession().setAttribute("baseUrl", baseUrl);
  82. }
  83. // 校验appId,appId为空的话默认为sso
  84. appId = StringUtils.isEmpty(appId) ? SSOHelper.getSSOService().getConfig().getAppName() : appId;
  85. App app = appService.findOne(appId);
  86. if (app == null) {
  87. return error("应用id不存在");
  88. }
  89. // 校验returnUrl,为空默认为优软云
  90. if (StringUtils.isEmpty(returnUrl)) {
  91. returnUrl = HOME_PAGE;
  92. }
  93. // 获取用户基本信息
  94. User user = userService.findByUsername(username);
  95. if (user == null) {
  96. return error("用户名或密码错误");
  97. }
  98. // 校验账户密码输错次数
  99. if (user.getUserRecord() == null) {
  100. UserRecord userRecord = userService.save(new UserRecord(user.getUserUU()));
  101. user.setUserRecord(userRecord);
  102. }
  103. int pwdErrorCount = user.getUserRecord() == null ? 0 : user.getUserRecord().getPwdErrorCount();
  104. Object loginCaptcha = request.getSession().getAttribute(LOGIN_CAPTCHA);
  105. String checkCode = loginCaptcha == null ? "" : loginCaptcha.toString();
  106. if (pwdErrorCount >= PWD_ERROR_FIVE_TIME) {
  107. return error("403", "密码错误次数已达上限,今日无法登陆");
  108. }
  109. // 校验账号是否被锁定,5次输错密码
  110. if (pwdErrorCount >= PWD_ERROR_THREE_TIME && StringUtils.isEmpty(captcha)) {
  111. return error("404", "验证码不能为空");
  112. }
  113. if (pwdErrorCount >= PWD_ERROR_THREE_TIME && !captcha.equalsIgnoreCase(checkCode)) {
  114. return error("验证码错误");
  115. }
  116. // 校验密码
  117. String encryPwd = userService.getEncryPassword(Const.ENCRY_FORMAT, password, user.getSalt());
  118. if (!encryPwd.equals(user.getPassword())) {
  119. pwdErrorCount = inputErrorPwd(user.getUserRecord());
  120. return error("您输入的账号或密码有误").addAttribute("errorCount", pwdErrorCount);
  121. }
  122. // 校验密码强度,如果和存储的不同,则保存
  123. int strength = PasswordLevelUtils.checkPasswordLevel(password).getValue();
  124. if (strength != user.getPasswordLevel()) {
  125. user.setPasswordLevel(strength);
  126. userService.save(user);
  127. }
  128. return success(login(user.getUserUU(), appId, spaceUU, returnUrl));
  129. }
  130. /**
  131. * 根据企业uu号和用户uu号获取登录token,有效期1分钟
  132. * @param enUU 企业uu号
  133. * @param userUU 用户uu号
  134. * @return tokenId,token存入ModelMap对象,值为 {userUU:用户uu号,spaceUU:企业uu号}
  135. */
  136. @RequestMapping(value = "/getToken", method = RequestMethod.GET)
  137. public ModelMap getToken(String enUU, String userUU, @RequestParam String appId) {
  138. ModelMap data = new ModelMap();
  139. if (enUU == null || userUU == null) {
  140. return error("参数错误");
  141. }
  142. // 根据企业uu号找到企业信息
  143. Userspace userspace = userspaceService.findOne(Long.valueOf(enUU));
  144. if (userspace == null) {
  145. return error(new ModelMap("hasUserSpace", false));
  146. }
  147. // 校验请求
  148. checkRequest(userspace.getAccessSecret());
  149. // 将企业信息、企业管理员信息写入SystemSession
  150. User user = userService.findOne(Long.valueOf(userUU));
  151. if (user == null) {
  152. return error(new ModelMap("hasUser", false));
  153. }
  154. if (!userspace.getUsers().contains(user)) {
  155. userService.bindUserspace(appId, user.getUserUU(), userspace.getSpaceUU());
  156. }
  157. data.put("spaceUU", enUU);
  158. data.put("userUU", userUU);
  159. // token有效期,单位秒
  160. int expires_in = 1 * 60;
  161. Token token = new Token(data, expires_in);
  162. tokenService.save(token);
  163. return success(token.getId());
  164. }
  165. /**
  166. * token代理页面
  167. * @return
  168. */
  169. @RequestMapping(value = "/proxy", method = RequestMethod.GET)
  170. public ModelAndView loginProxyByToken() {
  171. WafRequestWrapper wr = new WafRequestWrapper(request);
  172. String returnUrl = wr.getParameter("returnURL");
  173. String appId = wr.getParameter("appId");
  174. String token = wr.getParameter("token");
  175. String baseUrl = wr.getParameter("baseURL");
  176. String isLoginAll = wr.getParameter("isLoginAll");
  177. ModelMap data = new ModelMap();
  178. data.put("returnUrl", returnUrl);
  179. data.put("appId", appId);
  180. data.put("token", token);
  181. data.put("baseUrl", baseUrl);
  182. data.put("isLoginAll", isLoginAll == null ? true : isLoginAll);
  183. return new ModelAndView("/sso/proxyByToken", data);
  184. }
  185. /**
  186. * erp和uu互联跳转
  187. * 代理登录,根据tokenId拿到当前用户登录的用户uu号和企业uu号进行登录
  188. *
  189. * @param token tokenId
  190. * @param appId 应用id
  191. * @param returnUrl 跳转页面
  192. * @param baseUrl 而外登录接口
  193. * @return
  194. */
  195. @RequestMapping(value = "/proxy", method = RequestMethod.POST)
  196. public ModelMap loginProxyByToken(String token, String appId, String returnUrl, String baseUrl) {
  197. Token tk = tokenService.findOne(token);
  198. if (null != tk) {
  199. JSONObject data = JSON.parseObject(JSON.toJSONString(tk.getBind()));
  200. Long userUU = data.getLong("userUU");
  201. Long spaceUU = data.getLong("spaceUU");
  202. request.getSession().setAttribute("baseUrl", baseUrl);
  203. App app = appService.findOne(appId);
  204. if (app != null) {
  205. app = StringUtils.isEmpty(app.getUserControl()) ? app : appService.findOne(app.getUserControl());
  206. }
  207. if (app == null) {
  208. app = appService.findOne(AccountConfig.ACCOUNT_CENTER);
  209. }
  210. UserAccount userAccount = userAccountService.findOneByUserUU(app.getUid(), userUU, spaceUU);
  211. if (userAccount == null) {
  212. return success(new ModelMap("returnUrl", HttpUtil.decodeURL(returnUrl)));
  213. }
  214. return success(loginByUser(userAccount, returnUrl, true));
  215. }
  216. return success(new ModelMap("returnUrl", HttpUtil.decodeURL(returnUrl)));
  217. }
  218. /**
  219. * uu互联代理登录
  220. * @param token tokenId
  221. * @param appId 登录应用应用id
  222. * @param spaceUU 企业uu号
  223. * @param returnUrl 跳转页面
  224. * @return
  225. */
  226. @RequestMapping(value = "/mobile/proxy", method = RequestMethod.POST)
  227. public ModelMap loginProxyByToken(String token, @RequestParam(defaultValue = "sso") String appId, Long spaceUU, String returnUrl, String baseUrl) {
  228. Token tk = tokenService.findOne(token);
  229. if (tk == null) {
  230. return success(new ModelMap("returnUrl", HttpUtil.decodeURL(returnUrl)));
  231. }
  232. App app = appService.findOne(appId);
  233. baseUrl = StringUtils.isEmpty(baseUrl) ? app.getLoginUrl() : baseUrl;
  234. request.getSession().setAttribute("baseUrl", baseUrl);
  235. ModelMap modelMap = (ModelMap) tk.getBind();
  236. Long userUU = (Long) modelMap.get("userUU");
  237. if (modelMap.containsKey("spaceUU")) {
  238. spaceUU = (Long) modelMap.get("spaceUU");
  239. }
  240. if (app != null) {
  241. app = StringUtils.isEmpty(app.getUserControl()) ? app : appService.findOne(app.getUserControl());
  242. }
  243. if (app == null) {
  244. app = appService.findOne(AccountConfig.ACCOUNT_CENTER);
  245. }
  246. UserAccount userAccount = userAccountService.findOneByUserUU(app.getUid(), userUU, spaceUU);
  247. if (userAccount == null) {
  248. List<UserAccount> userAccounts = userAccountService.findByUserUU(app.getUid(), userUU);
  249. return success(getSpaceSelect(userAccounts, false));
  250. }
  251. return success(loginByUser(userAccount, returnUrl, false));
  252. }
  253. /**
  254. * uu互联更新token
  255. * @param token tokenId
  256. * @return 新token
  257. */
  258. @RequestMapping(value = "/updateToken", method = RequestMethod.GET)
  259. public ModelMap updateToken(String token) {
  260. Token oldToken = tokenService.findOne(token);
  261. oldToken.setExpires_in(7*24*60*60);
  262. tokenService.save(oldToken);
  263. return success(token);
  264. }
  265. @RequestMapping(value = "/mobile", method = RequestMethod.POST)
  266. public ModelMap getAllAccount(@RequestParam String mobile, String password) {
  267. User user = userService.findByMobile(mobile);
  268. List<ModelMap> allowedList = new ArrayList<ModelMap>();
  269. if (user == null) {
  270. return error("未找到用户信息");
  271. }
  272. // 校验密码
  273. userService.checkPasswordByMobile(mobile, password, false);
  274. userService.resetErrorCount(user.getUserUU());
  275. Long userUU = user.getUserUU();
  276. String userName = user.getVipName();
  277. List<ModelMap> spaces = new ArrayList<ModelMap>();
  278. Long imId = user.getImId() == null ? null : Long.valueOf(user.getImId());
  279. App b2b = appService.findOne("b2b");
  280. App uas = appService.findOne("uas");
  281. for (Userspace userspace : user.getUserSpaces()) {
  282. ModelMap space = new ModelMap();
  283. space.put("enuu", userspace.getSpaceUU());
  284. space.put("name", userspace.getSpaceName());
  285. space.put("businessCode", userspace.getBusinessCode());
  286. spaces.add(space);
  287. if (!StringUtils.isEmpty(userspace.getWebsite())) {
  288. ModelMap map = new ModelMap("platform", "ERP");
  289. map.put("account", user.getUserUU());
  290. map.put("master", "");
  291. map.put("name", userspace.getSpaceName());
  292. map.put("enuu", userspace.getSpaceUU());
  293. map.put("masterId", "");
  294. map.put("website", userspace.getWebsite()
  295. + (userspace.getWebsite() != null && !userspace.getWebsite().endsWith("/") ? "/" : ""));
  296. map.put("imid", imId);
  297. map.put("birthday", user.getBirthday());
  298. map.put("sex", user.getSex());
  299. map.put("businessCode", userspace.getBusinessCode());
  300. allowedList.add(map);
  301. }
  302. }
  303. Token token = new Token(new ModelMap("userUU", userUU), 7*24*60*60);
  304. tokenService.save(token);
  305. allowedList.add(new ModelMap("account", userUU).addAttribute("platform", "B2B").addAttribute("imid", imId).addAttribute("spaces", spaces).addAttribute("userName", userName));
  306. return new ModelMap("token", token.getId()).addAttribute("datalist", allowedList);
  307. }
  308. /**
  309. * 密码输错处理
  310. *
  311. * @param userRecord 用户登录记录
  312. * @return
  313. */
  314. private int inputErrorPwd(UserRecord userRecord) {
  315. // 密码输错次数+1
  316. int pwdErrorCount = userRecord.getPwdErrorCount();
  317. userRecord.setPwdErrorCount(++pwdErrorCount);
  318. userService.save(userRecord);
  319. // 设置返回值
  320. return pwdErrorCount;
  321. }
  322. /**
  323. * 根据用户名获得用户账号信息
  324. *
  325. * @param appId 应用
  326. * @param username 用户名
  327. * @return
  328. */
  329. private List<UserAccount> getUserAccountByUserName(String appId, String username) {
  330. String type = AccountTypeUtils.getAccountType(username);
  331. if (AccountTypeUtils.MOBILE.equals(type)) {
  332. // 手机号登录
  333. return userAccountService.findByMobile(appId, username);
  334. }
  335. if (AccountTypeUtils.EMAIL.equals(type)) {
  336. // 邮箱登录
  337. return userAccountService.findByEmail(appId, username);
  338. }
  339. if (AccountTypeUtils.UU_NUMBER.equals(type)) {
  340. // uu号登录
  341. return userAccountService.findByUserUU(appId, Long.valueOf(username));
  342. }
  343. // 其余情况
  344. return null;
  345. }
  346. /**
  347. * 根据用户名和企业uu找到用户信息
  348. *
  349. * @param appId 应用
  350. * @param username 用户名
  351. * @param spaceUU 企业uu号
  352. * @return
  353. */
  354. private UserAccount getUserAccountByUserName(String appId, String username, String spaceUU) {
  355. String type = AccountTypeUtils.getAccountType(username);
  356. if (AccountTypeUtils.MOBILE.equals(type)) {
  357. // 手机号登录
  358. return userAccountService.findOneByMobile(appId, username, Long.valueOf(spaceUU));
  359. }
  360. if (AccountTypeUtils.EMAIL.equals(type)) {
  361. // 邮箱登录
  362. return userAccountService.findOneByEmail(appId, username, Long.valueOf(spaceUU));
  363. }
  364. if (AccountTypeUtils.UU_NUMBER.equals(type)) {
  365. // uu号登录
  366. return userAccountService.findOneByUserUU(appId, Long.valueOf(username), Long.valueOf(spaceUU));
  367. }
  368. // 其余情况
  369. return null;
  370. }
  371. /**
  372. * 用户信息没问题,直接登录
  373. *
  374. * @param userAccount 用户账号信息
  375. * @param returnUrl 跳转url
  376. * @param isLoginAll 是否登录默认应用
  377. * @return
  378. */
  379. private ModelMap loginByUser(UserAccount userAccount, String returnUrl, boolean isLoginAll) {
  380. /*
  381. * 设置登录 Cookie 最后一个参数 true 时添加 cookie 同时销毁当前 JSESSIONID
  382. * 创建信任的 JSESSIONID
  383. */
  384. String baseUrl = (String) request.getSession().getAttribute("baseUrl");
  385. baseUrl = HttpUtil.decodeURL(baseUrl);
  386. SSOToken st = new SSOToken(request, userAccount.getMobile());
  387. st.setData(JSON.toJSONString(userAccount));
  388. SSOHelper.setSSOCookie(request, response, st, true);
  389. // 设置登录时间,并将密码输错次数设为0,为空则不设置
  390. UserRecord userRecord = new UserRecord(userAccount.getUserUU());
  391. userRecord.setLastLoginTime(System.currentTimeMillis());
  392. userService.save(userRecord);
  393. // 设置返回值,通知各个应用用户已经登录
  394. ModelMap data = new ModelMap();
  395. data = addOtherAppRequestData(userAccount, data, baseUrl, isLoginAll);
  396. data.put("returnUrl", HttpUtil.decodeURL(returnUrl));
  397. return data;
  398. }
  399. private ModelMap addOtherAppRequestData(UserAccount userAccount, ModelMap data, Object loginUrl,
  400. boolean isLoginAll) {
  401. List<App> apps = appService.findAll();
  402. List<String> loginUrls = new ArrayList<>();
  403. boolean hasLoginUrl = false;
  404. if (isLoginAll) {
  405. for (App app : apps) {
  406. if (StringUtils.isEmpty(app.getLoginUrl())) {
  407. continue;
  408. }
  409. if (app.getLoginUrl().equals(loginUrl)) {
  410. hasLoginUrl = true;
  411. }
  412. loginUrls.add(app.getLoginUrl());
  413. }
  414. }
  415. // 添加baseUrl
  416. if (!hasLoginUrl && !StringUtils.isEmpty(loginUrl)) {
  417. loginUrls.add(loginUrl.toString());
  418. }
  419. data.put("loginUrls", loginUrls);
  420. data.put("currentUrl", loginUrl);
  421. // 添加传递数据
  422. JSONObject jsonObject = JSON.parseObject(JSON.toJSONString(userAccount));
  423. Integer maxage = (Integer) request.getAttribute(SSOConfig.SSO_COOKIE_MAXAGE);
  424. jsonObject.put("maxage", maxage);
  425. data.put("data", jsonObject);
  426. return data;
  427. }
  428. /**
  429. * 获取选择企业信息(id:企业uu号,name:名称)
  430. *
  431. * @param userAccounts 用户账户信息
  432. * @param personalEnable 该应用是否允许个人账户
  433. * @return
  434. */
  435. private ModelMap getSpaceSelect(List<UserAccount> userAccounts, boolean personalEnable) {
  436. List<Map<String, Object>> spaces = new ArrayList<Map<String, Object>>();
  437. Map<String, Object> space = null;
  438. // 设置带企业账号
  439. for (UserAccount userAccount : userAccounts) {
  440. space = new HashMap<String, Object>(2);
  441. space.put("id", userAccount.getSpaceUU());
  442. space.put("name", userAccount.getSpaceName());
  443. spaces.add(space);
  444. }
  445. // 设置个人账号
  446. if (personalEnable) {
  447. space = new HashMap<String, Object>(2);
  448. space.put("id", Const.SPACEUU_PERSONAL);
  449. space.put("name", String.format("%s(个人)", userAccounts.get(0).getVipName()));
  450. spaces.add(space);
  451. }
  452. return new ModelMap("spaces", spaces);
  453. }
  454. @RequestMapping(value = "/checkCode", method = RequestMethod.GET)
  455. public void checkCode() {
  456. try {
  457. // 获取验证码
  458. CaptchaUtil.outputCaptcha(request, response, LOGIN_CAPTCHA);
  459. } catch (IOException e) {
  460. e.printStackTrace();
  461. }
  462. }
  463. /**
  464. * 获得密码输错次数
  465. *
  466. * @param username 用户名
  467. * @return
  468. */
  469. @RequestMapping(value = "/getPwdErrorCount", method = RequestMethod.GET)
  470. public ModelMap getPwdErrorCount(String username) {
  471. if (StringUtils.isEmpty(username)) {
  472. return error("用户名不能为空");
  473. }
  474. return success(userService.getPwdErrorCount(username.trim()));
  475. }
  476. /**
  477. * 退出接口,测试接口
  478. * @return
  479. */
  480. @RequestMapping(value = "/logoutAccount", method = RequestMethod.GET)
  481. public ModelMap logoutAccount() {
  482. SSOHelper.clearLogin(request, response);
  483. return success();
  484. }
  485. /**
  486. * 判断是否登录, 测试接口
  487. * @return
  488. */
  489. @RequestMapping(value = "/isLogin", method = RequestMethod.GET)
  490. public ModelMap isLogin() {
  491. SSOToken token = SSOHelper.getToken(request);
  492. return success(new ModelMap("isLogin", token != null));
  493. }
  494. /**
  495. * 页面样式
  496. * @param appId 应用id
  497. * @return
  498. */
  499. @RequestMapping(value = "/page/style", method = RequestMethod.GET)
  500. public ModelMap getPageStyle(@RequestParam(defaultValue = "sso") String appId) {
  501. App app = appService.findOne(appId);
  502. App defaultApp = appService.findOne("sso");
  503. PageStyle pageStyle = app == null ? defaultApp.getPageStyle() : app.getPageStyle();
  504. if (pageStyle != null) {
  505. BeanUtil.copyProperties(pageStyle, defaultApp.getPageStyle(), true);
  506. }
  507. return success(defaultApp.getPageStyle());
  508. }
  509. /**
  510. * 跨域询问,回复子系统是否登录
  511. *
  512. * @throws IOException
  513. */
  514. @RequestMapping("/ask")
  515. public void replyAsk() throws IOException {
  516. String callback = request.getParameter("callback");
  517. SSOToken token = SSOHelper.getToken(request);
  518. if (token != null) {
  519. String askData = request.getParameter("askData");
  520. if (!StringUtils.isEmpty(askData)) {
  521. // 下面开始验证票据,签名新的票据每一步都必须有。
  522. AuthToken at = SSOHelper.replyCiphertext(request, askData);
  523. if (at != null) {
  524. App app = appService.findOne(at.getApp());
  525. if (app != null && StringUtils.isEmpty(app.getPublicKey()) && !StringUtils.isEmpty(app.getUserControl())) {
  526. app = appService.findOne(app.getUserControl());
  527. }
  528. if (app == null) {
  529. printJsonP(callback, error("403", "非法签名"));
  530. return;
  531. }
  532. // 对应系统公钥验证签名
  533. at = at.verify(app.getPublicKey());
  534. if (at != null) {
  535. at.setUid(token.getUid());// 设置绑定用户ID
  536. at.setTime(token.getTime());// 设置登录时间
  537. // 更安全的做法是使用at.getUuid() 作为 key 设置 authToken
  538. // 至分布式缓存中,然后 这里根据UUID验证和赋值
  539. at.setData(token.getData());
  540. // 2、SSO 的私钥签名
  541. at.sign(SSOConfig.getInstance().getCenterPrivateKey());
  542. // 3、生成回复密文票据
  543. printJsonP(callback, success(at.encryptAuthToken()));
  544. } else {
  545. // 非法签名, 可以重定向至无权限界面,App自己处理
  546. printJsonP(callback, error("403", "非法签名"));
  547. }
  548. } else {
  549. // 非法签名, 可以重定向至无权限界面,App自己处理
  550. printJsonP(callback, error("403", "非法签名"));
  551. }
  552. }
  553. } else {
  554. // 未登录
  555. printJsonP(callback, error("404", "未登录"));
  556. }
  557. }
  558. /**
  559. * 跨域切换企业
  560. * @param spaceUU 企业uu号
  561. * @throws IOException
  562. */
  563. @RequestMapping(value = "/change/userspace", method = RequestMethod.GET)
  564. @ResponseBody
  565. public void changeUserSpace(Long spaceUU) throws IOException {
  566. String callback = request.getParameter("callback");
  567. response.setContentType("text/html;charset=UTF-8");
  568. SSOToken token = SSOHelper.getToken(request);
  569. if (token != null) {
  570. SSOToken st = SSOHelper.getToken(request);
  571. UserAccount user = JSON.parseObject(st.getData(), UserAccount.class);
  572. user = userAccountService.findOneByUserUU(user.getAppId(), user.getUserUU(), spaceUU);
  573. if (user == null) {
  574. printJsonP(callback, error("403", "切换账号失败"));
  575. }
  576. st.setData(JSON.toJSONString(user));
  577. SSOHelper.setSSOCookie(request, response, st, true);
  578. printJsonP(callback, success());
  579. } else {
  580. // 未登录
  581. printJsonP(callback, error("404", "未登录"));
  582. }
  583. }
  584. /**
  585. * 发送手机验证码
  586. * @param mobile 手机号
  587. * @return
  588. */
  589. @RequestMapping(value = "/sendSmsCode", method = RequestMethod.GET)
  590. public ModelMap sendSmsCode(String mobile) {
  591. Assert.hasText(mobile, "手机号不能为空");
  592. mobile = StringUtils.trimAllWhitespace(mobile);
  593. // 校验手机号是否被注册
  594. boolean hasRegister = userService.mobileHasRegistered(mobile);
  595. if (!hasRegister) {
  596. return error("该手机号未注册,请先注册");
  597. }
  598. // 随机获得验证码
  599. String code = StringUtil.getRandomNumber(6);
  600. Token token = new Token(code, 10 * 60);
  601. System.out.println(code);
  602. // 设置绑定手机,防止获取验证码之后修改手机号
  603. token.setMobile(mobile);
  604. tokenService.save(token);
  605. // 发送短信
  606. MessageUtils.sendSms("templateForSendSmsWhenLogin", mobile, code);
  607. // 返回tokenId
  608. ModelMap returnData = new ModelMap();
  609. returnData.put("token", token.getId());
  610. return success(returnData);
  611. }
  612. /**
  613. * 根据手机号验证码登录
  614. * @return
  615. */
  616. @RequestMapping(value = "/sms", method = RequestMethod.POST)
  617. public ModelMap loginBySms(String code, String token) {
  618. // 获取登录信息
  619. WafRequestWrapper wr = new WafRequestWrapper(request);
  620. String appId = wr.getParameter("appId");
  621. String spaceUU = wr.getParameter("spaceUU");
  622. String mobile = StringUtils.trimAllWhitespace(wr.getParameter("mobile"));
  623. String returnUrl = wr.getParameter("returnUrl");
  624. String baseUrl = wr.getParameter("baseUrl");
  625. appId = StringUtils.isEmpty(appId) ? AccountConfig.ACCOUNT_CENTER : appId;
  626. // 校验手机号是否被注册
  627. boolean hasRegister = userService.mobileHasRegistered(mobile);
  628. if (!hasRegister) {
  629. return error("该手机号未注册,请先注册");
  630. }
  631. // 设置baseUrl
  632. if (!StringUtils.isEmpty(baseUrl)) {
  633. request.getSession().setAttribute("baseUrl", baseUrl);
  634. }
  635. // 校验token
  636. Assert.hasText(token, "请先获取验证码");
  637. Token existToken = tokenService.findOne(token);
  638. if (existToken == null || existToken.isExpired()) {
  639. return error("验证码已过期,请重新获取");
  640. }
  641. if (!StringUtils.isEmpty(existToken.getMobile()) && !existToken.getMobile().equals(mobile)) {
  642. return error("手机号被修改,请重新获取验证码");
  643. }
  644. if (StringUtils.isEmpty(code) || !code.equals(existToken.getBind())) {
  645. return error("验证码错误");
  646. }
  647. // 获取登录用户
  648. User user = userService.findByMobile(mobile);
  649. if (user == null) {
  650. return error("该手机号未注册");
  651. }
  652. return success(login(user.getUserUU(), appId, spaceUU, returnUrl));
  653. }
  654. /**
  655. * 登录处理
  656. * @param userUU 用户uu号
  657. * @param appId 应用id
  658. * @param spaceUU 企业uu号
  659. * @param returnUrl 跳转地址
  660. * @return
  661. */
  662. private ModelMap login(Long userUU, String appId, String spaceUU, String returnUrl) {
  663. // 登录
  664. appId = StringUtils.isEmpty(appId) ? AccountConfig.ACCOUNT_CENTER : appId;
  665. App app = appService.findOne(appId);
  666. if (app == null) {
  667. throw new VerifyError("应用不存在");
  668. }
  669. App controlApp = StringUtils.isEmpty(app.getUserControl()) ? app : appService.findOne(app.getUserControl());
  670. boolean personalEnable = Const.YES == controlApp.getPersonalEnable();
  671. if (StringUtils.isEmpty(spaceUU)) {
  672. /*企业uu号为空,让用户选择企业*/
  673. // 找到用户账号信息
  674. List<UserAccount> userAccounts = userAccountService.findByUserUU(controlApp.getUid(), userUU);
  675. // 没有记录
  676. if (CollectionUtils.isEmpty(userAccounts)) {
  677. // 没有记录如果当前应用允许个人账号的话,查找个人账号
  678. UserAccount userAccount = personalAccountService.findOneByUserUU(controlApp.getUid(), userUU);
  679. if (!personalEnable) {
  680. // 不支持个人账号则跳转优软云
  681. returnUrl = HOME_PAGE;
  682. }
  683. return loginByUser(userAccount, returnUrl, true);
  684. }
  685. // 应用允许个人账号,并且账号未绑定企业,或者只绑定了一个企业,直接登录
  686. if (userAccounts.size() == 1) {
  687. return loginByUser(userAccounts.get(0), returnUrl, true);
  688. }
  689. // 返回企业id和名称
  690. return getSpaceSelect(userAccounts, personalEnable);
  691. } else if (personalEnable && Long.valueOf(spaceUU).equals(Const.SPACEUU_PERSONAL)) {
  692. // 使用个人账号登录
  693. UserAccount userAccount = personalAccountService.findOneByUserUU(controlApp.getUid(), userUU);
  694. return loginByUser(userAccount, returnUrl, true);
  695. } else {
  696. // 带企业登录
  697. UserAccount userAccount = userAccountService.findOneByUserUU(controlApp.getUid(), userUU, Long.valueOf(spaceUU));
  698. return loginByUser(userAccount, returnUrl, true);
  699. }
  700. }
  701. /**
  702. * 微信获取code
  703. * @param code 获取用户信息的code
  704. * @param state 验证请求
  705. * @return
  706. */
  707. @RequestMapping(value = "/wxqrLogin", method = RequestMethod.POST)
  708. public ModelMap wxqrLogin(String code, String state) {
  709. // TODO 校验state
  710. // 获取用户信息
  711. OAuthInfo oAuthInfo = weChatService.getOAuthInfoByCode(code);
  712. User user = null;
  713. if (oAuthInfo == null || StringUtils.isEmpty(oAuthInfo.getAccess_token())) {
  714. Long userUU = (Long) request.getSession().getAttribute("userUU");
  715. if (userUU == null) {
  716. return error("验证信息过期,请重新扫码登录");
  717. }
  718. user = new User(userUU);
  719. } else {
  720. user = userService.findByWxUnionid(oAuthInfo.getUnionid());
  721. if (user == null) {
  722. // 提示前端用户微信未绑定账号
  723. Token token = new Token(oAuthInfo.getUnionid(), oAuthInfo.getExpires_in());
  724. ModelMap data = new ModelMap("hasRegister", false);
  725. data.put("token", token.getId());
  726. return success(data);
  727. }
  728. request.getSession().setAttribute("userUU", user.getUserUU());
  729. }
  730. // 登录
  731. WafRequestWrapper wr = new WafRequestWrapper(request);
  732. String appId = wr.getParameter("appId");
  733. String spaceUU = wr.getParameter("spaceUU");
  734. String returnUrl = wr.getParameter("returnUrl");
  735. String baseUrl = wr.getParameter("baseUrl");
  736. request.getSession().setAttribute("baseUrl", baseUrl);
  737. return success(login(user.getUserUU(), appId, spaceUU, returnUrl));
  738. }
  739. }