|
@@ -2,28 +2,24 @@ package com.uas.sso.controller;
|
|
|
|
|
|
|
|
import com.alibaba.fastjson.JSON;
|
|
import com.alibaba.fastjson.JSON;
|
|
|
import com.alibaba.fastjson.JSONObject;
|
|
import com.alibaba.fastjson.JSONObject;
|
|
|
-import com.uas.sso.SSOConfig;
|
|
|
|
|
-import com.uas.sso.SSOHelper;
|
|
|
|
|
-import com.uas.sso.SSOToken;
|
|
|
|
|
|
|
+import com.uas.account.AccountConfig;
|
|
|
|
|
+import com.uas.sso.*;
|
|
|
import com.uas.sso.common.util.HttpUtil;
|
|
import com.uas.sso.common.util.HttpUtil;
|
|
|
import com.uas.sso.core.Const;
|
|
import com.uas.sso.core.Const;
|
|
|
import com.uas.sso.entity.*;
|
|
import com.uas.sso.entity.*;
|
|
|
-import com.uas.sso.service.AppService;
|
|
|
|
|
-import com.uas.sso.service.PersonalAccountService;
|
|
|
|
|
-import com.uas.sso.service.UserService;
|
|
|
|
|
-import com.uas.sso.service.UserAccountService;
|
|
|
|
|
|
|
+import com.uas.sso.entity.Token;
|
|
|
|
|
+import com.uas.sso.service.*;
|
|
|
import com.uas.sso.util.AccountTypeUtils;
|
|
import com.uas.sso.util.AccountTypeUtils;
|
|
|
import com.uas.sso.util.BeanUtil;
|
|
import com.uas.sso.util.BeanUtil;
|
|
|
import com.uas.sso.util.CaptchaUtil;
|
|
import com.uas.sso.util.CaptchaUtil;
|
|
|
|
|
+import com.uas.sso.util.encry.HmacUtils;
|
|
|
import com.uas.sso.web.waf.request.WafRequestWrapper;
|
|
import com.uas.sso.web.waf.request.WafRequestWrapper;
|
|
|
import org.springframework.beans.factory.annotation.Autowired;
|
|
import org.springframework.beans.factory.annotation.Autowired;
|
|
|
import org.springframework.ui.ModelMap;
|
|
import org.springframework.ui.ModelMap;
|
|
|
import org.springframework.util.CollectionUtils;
|
|
import org.springframework.util.CollectionUtils;
|
|
|
import org.springframework.util.StringUtils;
|
|
import org.springframework.util.StringUtils;
|
|
|
-import org.springframework.web.bind.annotation.RequestMapping;
|
|
|
|
|
-import org.springframework.web.bind.annotation.RequestMethod;
|
|
|
|
|
-import org.springframework.web.bind.annotation.RequestParam;
|
|
|
|
|
-import org.springframework.web.bind.annotation.RestController;
|
|
|
|
|
|
|
+import org.springframework.web.bind.annotation.*;
|
|
|
|
|
+import org.springframework.web.servlet.ModelAndView;
|
|
|
|
|
|
|
|
import java.io.IOException;
|
|
import java.io.IOException;
|
|
|
import java.util.*;
|
|
import java.util.*;
|
|
@@ -64,6 +60,9 @@ public class LoginController extends BaseController {
|
|
|
@Autowired
|
|
@Autowired
|
|
|
private UserService userService;
|
|
private UserService userService;
|
|
|
|
|
|
|
|
|
|
+ @Autowired
|
|
|
|
|
+ private UserspaceService userspaceService;
|
|
|
|
|
+
|
|
|
@Autowired
|
|
@Autowired
|
|
|
private UserAccountService userAccountService;
|
|
private UserAccountService userAccountService;
|
|
|
|
|
|
|
@@ -180,6 +179,114 @@ public class LoginController extends BaseController {
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+ /**
|
|
|
|
|
+ * 根据企业uu号和用户uu号获取登录token,有效期1分钟
|
|
|
|
|
+ * @param enUU 企业uu号
|
|
|
|
|
+ * @param userUU 用户uu号
|
|
|
|
|
+ * @param timestamp 请求时间,用于判断请求是否有效,有效期10秒
|
|
|
|
|
+ * @param signature 加密信息,使用企业私钥加密请求参数
|
|
|
|
|
+ * @return tokenId,token存入ModelMap对象,值为 {userUU:用户uu号,spaceUU:企业uu号}
|
|
|
|
|
+ */
|
|
|
|
|
+ @RequestMapping(value = "/getToken", method = RequestMethod.GET)
|
|
|
|
|
+ public ModelMap getToken(String enUU, String userUU, @RequestParam(name = "_timestamp") Long timestamp, @RequestParam(name = "_signature") String signature) {
|
|
|
|
|
+ ModelMap map = new ModelMap();
|
|
|
|
|
+
|
|
|
|
|
+ // 根据企业uu号找到企业信息
|
|
|
|
|
+ Userspace userspace = userspaceService.findOne(Long.valueOf(enUU));
|
|
|
|
|
+ if (userspace == null) {
|
|
|
|
|
+ return error("没有找到企业");
|
|
|
|
|
+ }
|
|
|
|
|
+ if (userspace.getAccessSecret() == null) {
|
|
|
|
|
+ return error("接口未授权");
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // 请求时间不小于当前时间10秒,单位毫秒
|
|
|
|
|
+ long expires_request = 10 * 1000;
|
|
|
|
|
+ if (System.currentTimeMillis() - timestamp > expires_request || System.currentTimeMillis() < timestamp) {
|
|
|
|
|
+ return error("请求超时");
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // 判断加密信息是否有误
|
|
|
|
|
+ String urlMessage = request.getRequestURL() + "?"
|
|
|
|
|
+ + request.getQueryString().substring(0, request.getQueryString().indexOf("_signature") - 1);
|
|
|
|
|
+ if (!signature.equals(HmacUtils.encode(urlMessage, userspace.getAccessSecret()))) {
|
|
|
|
|
+ return error("密钥错误");
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // 将企业信息、企业管理员信息写入SystemSession
|
|
|
|
|
+ User user = userService.findOne(Long.valueOf(userUU));
|
|
|
|
|
+ if (user == null) {
|
|
|
|
|
+ return error("没有找到用户");
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ if (!userspace.getUsers().contains(user)) {
|
|
|
|
|
+ return error("该用户不在当前企业");
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ map.put("spaceUU", enUU);
|
|
|
|
|
+ map.put("userUU", userUU);
|
|
|
|
|
+ // token有效期,单位秒
|
|
|
|
|
+ int expires_in = 1 * 60;
|
|
|
|
|
+ Token token = new Token(map, expires_in);
|
|
|
|
|
+ tokenService.save(token);
|
|
|
|
|
+ return success(token.getId());
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * token代理页面
|
|
|
|
|
+ * @return
|
|
|
|
|
+ */
|
|
|
|
|
+ @RequestMapping(value = "/proxy", method = RequestMethod.GET)
|
|
|
|
|
+ public ModelAndView loginProxyByToken() {
|
|
|
|
|
+ WafRequestWrapper wr = new WafRequestWrapper(request);
|
|
|
|
|
+ String returnUrl = wr.getParameter("returnURL");
|
|
|
|
|
+ String appId = wr.getParameter("appId");
|
|
|
|
|
+ String token = wr.getParameter("token");
|
|
|
|
|
+ String baseUrl = wr.getParameter("baseURL");
|
|
|
|
|
+ String isLoginAll = wr.getParameter("isLoginAll");
|
|
|
|
|
+ ModelMap data = new ModelMap();
|
|
|
|
|
+ data.put("returnUrl", returnUrl);
|
|
|
|
|
+ data.put("appId", appId);
|
|
|
|
|
+ data.put("token", token);
|
|
|
|
|
+ data.put("baseUrl", baseUrl);
|
|
|
|
|
+ data.put("isLoginAll", isLoginAll == null ? true : isLoginAll);
|
|
|
|
|
+ return new ModelAndView("/sso/proxyByToken", data);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * erp和uu互联跳转
|
|
|
|
|
+ * 代理登录,根据tokenId拿到当前用户登录的用户uu号和企业uu号进行登录
|
|
|
|
|
+ *
|
|
|
|
|
+ * @param token tokenId
|
|
|
|
|
+ * @param appId 应用id
|
|
|
|
|
+ * @param returnUrl 跳转页面
|
|
|
|
|
+ * @param baseUrl 而外登录接口
|
|
|
|
|
+ * @param isLoginAll 是否登录默认应用
|
|
|
|
|
+ * @return
|
|
|
|
|
+ */
|
|
|
|
|
+ @RequestMapping(value = "/proxy", method = RequestMethod.POST)
|
|
|
|
|
+ public ModelMap loginProxyByToken(String token, String appId, String returnUrl, String baseUrl, @RequestParam(defaultValue = "true") boolean isLoginAll) {
|
|
|
|
|
+ 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 (app == null) {
|
|
|
|
|
+ app = appService.findOne(AccountConfig.ACCOUNT_CENTER);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ UserAccount userAccount = userAccountService.findOneByUserUU(app.getUid(), userUU, spaceUU);
|
|
|
|
|
+ return loginByUser(userAccount, returnUrl, null);
|
|
|
|
|
+ }
|
|
|
|
|
+ return error("验证信息已过期");
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
/**
|
|
/**
|
|
|
* 密码输错处理
|
|
* 密码输错处理
|
|
|
*
|
|
*
|
|
@@ -266,10 +373,12 @@ public class LoginController extends BaseController {
|
|
|
st.setData(JSON.toJSONString(userAccount));
|
|
st.setData(JSON.toJSONString(userAccount));
|
|
|
SSOHelper.setSSOCookie(request, response, st, true);
|
|
SSOHelper.setSSOCookie(request, response, st, true);
|
|
|
|
|
|
|
|
- // 设置登录时间,并将密码输错次数设为0
|
|
|
|
|
- userRecord.setLastLoginTime(System.currentTimeMillis());
|
|
|
|
|
- userRecord.setPwdErrorCount(0);
|
|
|
|
|
- userService.save(userRecord);
|
|
|
|
|
|
|
+ // 设置登录时间,并将密码输错次数设为0,为空则不设置
|
|
|
|
|
+ if (userRecord != null) {
|
|
|
|
|
+ userRecord.setLastLoginTime(System.currentTimeMillis());
|
|
|
|
|
+ userRecord.setPwdErrorCount(0);
|
|
|
|
|
+ userService.save(userRecord);
|
|
|
|
|
+ }
|
|
|
|
|
|
|
|
// 设置返回值,通知各个应用用户已经登录
|
|
// 设置返回值,通知各个应用用户已经登录
|
|
|
ModelMap data = new ModelMap();
|
|
ModelMap data = new ModelMap();
|
|
@@ -366,8 +475,8 @@ public class LoginController extends BaseController {
|
|
|
* 退出接口,测试接口
|
|
* 退出接口,测试接口
|
|
|
* @return
|
|
* @return
|
|
|
*/
|
|
*/
|
|
|
- @RequestMapping(value = "/logout", method = RequestMethod.GET)
|
|
|
|
|
- public ModelMap logout() {
|
|
|
|
|
|
|
+ @RequestMapping(value = "/logoutAccount", method = RequestMethod.GET)
|
|
|
|
|
+ public ModelMap logoutAccount() {
|
|
|
SSOHelper.clearLogin(request, response);
|
|
SSOHelper.clearLogin(request, response);
|
|
|
return success();
|
|
return success();
|
|
|
}
|
|
}
|
|
@@ -395,4 +504,117 @@ public class LoginController extends BaseController {
|
|
|
BeanUtil.copyProperties(pageStyle, defaultApp.getPageStyle(), true);
|
|
BeanUtil.copyProperties(pageStyle, defaultApp.getPageStyle(), true);
|
|
|
return success(defaultApp.getPageStyle());
|
|
return success(defaultApp.getPageStyle());
|
|
|
}
|
|
}
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * 跨域询问,回复子系统是否登录
|
|
|
|
|
+ *
|
|
|
|
|
+ * @throws IOException
|
|
|
|
|
+ */
|
|
|
|
|
+ @RequestMapping("/login/ask")
|
|
|
|
|
+ @ResponseBody
|
|
|
|
|
+ public void replyAsk() throws IOException {
|
|
|
|
|
+ String callback = request.getParameter("callback");
|
|
|
|
|
+ SSOToken token = SSOHelper.getToken(request);
|
|
|
|
|
+ if (token != null) {
|
|
|
|
|
+ String askData = request.getParameter("askData");
|
|
|
|
|
+ if (!StringUtils.isEmpty(askData)) {
|
|
|
|
|
+ // 下面开始验证票据,签名新的票据每一步都必须有。
|
|
|
|
|
+ AuthToken at = SSOHelper.replyCiphertext(request, askData);
|
|
|
|
|
+ if (at != null) {
|
|
|
|
|
+ App app = appService.findOne(at.getApp());
|
|
|
|
|
+ if (app != null && StringUtils.isEmpty(app.getPublicKey()) && !StringUtils.isEmpty(app.getUserControl())) {
|
|
|
|
|
+ app = appService.findOne(app.getUserControl());
|
|
|
|
|
+ }
|
|
|
|
|
+ if (app == null) {
|
|
|
|
|
+ printJsonP(callback, error("403", "非法签名"));
|
|
|
|
|
+ return;
|
|
|
|
|
+ }
|
|
|
|
|
+ // 对应系统公钥验证签名
|
|
|
|
|
+ at = at.verify(app.getPublicKey());
|
|
|
|
|
+ if (at != null) {
|
|
|
|
|
+ at.setUid(token.getUid());// 设置绑定用户ID
|
|
|
|
|
+ at.setTime(token.getTime());// 设置登录时间
|
|
|
|
|
+ // 更安全的做法是使用at.getUuid() 作为 key 设置 authToken
|
|
|
|
|
+ // 至分布式缓存中,然后 这里根据UUID验证和赋值
|
|
|
|
|
+ at.setData(token.getData());
|
|
|
|
|
+
|
|
|
|
|
+ // 2、SSO 的私钥签名
|
|
|
|
|
+ at.sign(SSOConfig.getInstance().getCenterPrivateKey());
|
|
|
|
|
+
|
|
|
|
|
+ // 3、生成回复密文票据
|
|
|
|
|
+ printJsonP(callback, success(at.encryptAuthToken()));
|
|
|
|
|
+ } else {
|
|
|
|
|
+ // 非法签名, 可以重定向至无权限界面,App自己处理
|
|
|
|
|
+ printJsonP(callback, error("403", "非法签名"));
|
|
|
|
|
+ }
|
|
|
|
|
+ } else {
|
|
|
|
|
+ // 非法签名, 可以重定向至无权限界面,App自己处理
|
|
|
|
|
+ printJsonP(callback, error("403", "非法签名"));
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ } else {
|
|
|
|
|
+ // 未登录
|
|
|
|
|
+ printJsonP(callback, error("404", "未登录"));
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * 跨域询问,随子系统一起退出
|
|
|
|
|
+ *
|
|
|
|
|
+ * @throws IOException
|
|
|
|
|
+ */
|
|
|
|
|
+ @RequestMapping(value = "/logout/ask", method = RequestMethod.GET)
|
|
|
|
|
+ @ResponseBody
|
|
|
|
|
+ public void replyAskOut() throws IOException {
|
|
|
|
|
+ String callback = request.getParameter("callback");
|
|
|
|
|
+ SSOToken token = SSOHelper.getToken(request);
|
|
|
|
|
+ if (token != null) {
|
|
|
|
|
+ // 已登录
|
|
|
|
|
+ printJsonP(callback, error("404", "已登录"));
|
|
|
|
|
+ } else {
|
|
|
|
|
+ printJsonP(callback, success());
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * 随子系统一起退出
|
|
|
|
|
+ *
|
|
|
|
|
+ * @throws IOException
|
|
|
|
|
+ */
|
|
|
|
|
+ @RequestMapping(value = "/logout", method = RequestMethod.GET)
|
|
|
|
|
+ @ResponseBody
|
|
|
|
|
+ public ModelMap logout() throws IOException {
|
|
|
|
|
+ System.err.print(request.getContextPath());
|
|
|
|
|
+ System.err.print(request.getHeaderNames().toString());
|
|
|
|
|
+ System.err.print(request.getCookies());
|
|
|
|
|
+ String callback = request.getParameter("callback");
|
|
|
|
|
+ String returnURL = request.getParameter("returnURL") == null ? HOME_PAGE : request.getParameter("returnURL");
|
|
|
|
|
+ String baseUrl = request.getParameter("baseUrl");
|
|
|
|
|
+ String appId = request.getParameter("appId") == null ? "sso" : request.getParameter("appId");
|
|
|
|
|
+ SSOToken token = SSOHelper.getToken(request);
|
|
|
|
|
+ ModelMap modelMap = new ModelMap();
|
|
|
|
|
+ modelMap.addAttribute("callback", callback);
|
|
|
|
|
+ modelMap.addAttribute("returnURL", HttpUtil.decodeURL(returnURL));
|
|
|
|
|
+ modelMap.addAttribute("appId", appId);
|
|
|
|
|
+ modelMap.addAttribute("logoutUrls", getOtherLogoutUrls(baseUrl));
|
|
|
|
|
+
|
|
|
|
|
+ if (token != null) {
|
|
|
|
|
+ SSOHelper.clearLogin(request, response);
|
|
|
|
|
+ }
|
|
|
|
|
+ return success(modelMap);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ private Set<String> getOtherLogoutUrls(String baseUrl) {
|
|
|
|
|
+ List<App> apps = appService.findAll();
|
|
|
|
|
+ Set<String> logoutUrls = new HashSet<>();
|
|
|
|
|
+ for (App app : apps) {
|
|
|
|
|
+ if (!StringUtils.isEmpty(app.getLogoutUrl())) {
|
|
|
|
|
+ logoutUrls.add(app.getLogoutUrl());
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ logoutUrls.add(baseUrl);
|
|
|
|
|
+ return logoutUrls;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
}
|
|
}
|