package com.vci.web.controller; import com.vci.starter.web.annotation.controller.VciUnCheckRight; import com.vci.starter.web.annotation.log.VciBusinessLog; import com.vci.starter.web.constant.TokenKeyConstant; import com.vci.starter.web.pagemodel.BaseResult; import com.vci.starter.web.pagemodel.RequestClientInfo; import com.vci.starter.web.pagemodel.SessionInfo; import com.vci.starter.web.util.LangBaseUtil; import com.vci.starter.web.util.MessageUtils; import com.vci.starter.web.util.VciBaseUtil; import com.vci.starter.web.util.WebThreadLocalUtil; import com.vci.web.bo.LoginResultBO; import com.vci.web.dto.LoginUserDTO; import com.vci.web.service.LoginServiceI; import eu.bitwalker.useragentutils.*; import org.apache.commons.lang3.StringUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.ResponseBody; import org.springframework.web.servlet.ModelAndView; import javax.servlet.http.Cookie; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.security.Principal; import java.util.Enumeration; import java.util.HashMap; import java.util.Locale; import java.util.Map; /** * 登录控制器 * @author weidy * @date 2021-1-28 */ @Controller @RequestMapping("/framework/loginController") @VciBusinessLog(modelName="登录服务") public class LoginController{ /** * 登录服务 */ @Autowired private LoginServiceI loginService; /** * 登录,这个地方主要是为了登录后单独的业务 * @param userDTO 用户的对象 * @param request 请求对象 * @param clientInfo 客户端的信息 * @return 执行结果 */ @VciBusinessLog(operateName="登录") @PostMapping(value = "/login") @ResponseBody @VciUnCheckRight() public BaseResult login(LoginUserDTO userDTO, HttpServletRequest request, RequestClientInfo clientInfo){ VciBaseUtil.alertNotNull(userDTO,"用户对象",clientInfo,"请求客户端信息"); wrapperBrowserInfo(clientInfo,request); LoginResultBO loginResultBO = loginService.login(userDTO,clientInfo); if(loginResultBO.isSuccess()){ return BaseResult.success(loginResultBO); }else{ BaseResult result = BaseResult.fail(loginResultBO.getFailMsg()); if(StringUtils.isBlank(loginResultBO.getFailMsg())){ result.setMsg(MessageUtils.get(loginResultBO.getFailCode(),loginResultBO.getFailMsgArray())); } result.setObj(loginResultBO); return result; } } /** * CAS的单点登录 * 1. cas单点登录,则从userPrincipal里获取 * 2. 在头里面加iv-user * 3. 在request里面放用户 * @param request 请求的对象 * @param response 响应对象 * @return html的名字的前缀,具体是Jsp还是html,是spring-mvc里配置的 */ @VciBusinessLog(operateName="单点登录") @RequestMapping("/singleLoginCas") @VciUnCheckRight() public ModelAndView singleLoginCas(HttpServletRequest request,HttpServletResponse response){ return doSingleLogin(request,response,""); } /** * 执行单点登录 * @param request 请求的信息 * @param userParam 用户的参数名字 * @return 返回main.html */ private ModelAndView doSingleLogin(HttpServletRequest request, HttpServletResponse response,String userParam){ String msg = ""; String token = ""; if(request.getSession() == null){ msg = "session已经过期或不存在,你可能需要重新执行单点登录"; }else { String username = ""; Principal principal = request.getUserPrincipal(); if(principal!=null){ Object ivUser = principal.getName(); if (ivUser != null ) { username = ivUser.toString(); } } //用户的参数 if(StringUtils.isBlank(userParam)){ userParam = request.getParameter("userParam"); } userParam = StringUtils.isBlank(userParam)?"iv-user":userParam; if(StringUtils.isBlank(username)){ //不是cas的方式,而是头的方式 username = request.getHeader(userParam); } if(StringUtils.isBlank(username)){ //看看是不参数 username = request.getParameter(userParam); } if(StringUtils.isBlank(username)){ msg = "没有获取到用户的信息"; }else{ RequestClientInfo clientInfo =new RequestClientInfo(); wrapperBrowserInfo(clientInfo,request); LoginUserDTO userDTO = new LoginUserDTO(); userDTO.setUserId(username); try { LoginResultBO loginResultBO = loginService.singleLogin(userDTO, clientInfo); if(!loginResultBO.isSuccess()){ msg = loginResultBO.getFailMsg(); }else { token = loginResultBO.getTokenVO().getAccessToken(); } }catch (Throwable e){ msg = LangBaseUtil.getErrorMsg(e); } } } Enumeration parameterNames = request.getParameterNames(); Map paramMap = new HashMap<>(); while (parameterNames.hasMoreElements()){ String paramName = (String)parameterNames.nextElement(); String value = request.getParameter(paramName); if(!userParam.equalsIgnoreCase(paramName)) { paramMap.put(paramName, value); } //sb.append("&" + paramName + "=" + value); } String html = request.getParameter("html"); if(StringUtils.isBlank(html)){ html = "main"; } ModelAndView view = new ModelAndView(); Cookie cookie = new Cookie("msg", msg); cookie.setPath("/"); response.addCookie(cookie); Cookie cookie1 = new Cookie(TokenKeyConstant.USER_TOKEN_KEY, token); cookie1.setPath("/"); response.addCookie(cookie1); view.addAllObjects(paramMap); view.setViewName("redirect:/" + html + ".html"); return view; //特别注意,单点登录一定在运行环境里调试,开发环境没有这个文件 } /** * 执行单点登录,根据username * @param request 请求的信息 * @param username 用户的参数名字 * @return 返回main.html */ public BaseResult doSingleLoginByUsername(HttpServletRequest request, HttpServletResponse response,String username){ String msg = ""; String token = ""; if(request.getSession() == null){ msg = "session已经过期或不存在,你可能需要重新执行单点登录"; return BaseResult.fail(msg); }else { if(StringUtils.isBlank(username)){ msg = "没有获取到用户的信息"; return BaseResult.fail(msg); }else{ RequestClientInfo clientInfo =new RequestClientInfo(); wrapperBrowserInfo(clientInfo,request); LoginUserDTO userDTO = new LoginUserDTO(); userDTO.setUserId(username); try { LoginResultBO loginResultBO = loginService.singleLogin(userDTO, clientInfo); if(!loginResultBO.isSuccess()){ msg = loginResultBO.getFailMsg(); return BaseResult.fail(msg); }else { token = loginResultBO.getTokenVO().getAccessToken(); msg="登录成功!"; } }catch (Throwable e){ msg = LangBaseUtil.getErrorMsg(e); } } } return BaseResult.success(msg); //特别注意,单点登录一定在运行环境里调试,开发环境没有这个文件 } /** * 使用用户名来执行单点登录 * @param request 请求对象 * @param response 响应对象 * @return main.html */ @RequestMapping("/singleLoginByUsername") @VciUnCheckRight @VciBusinessLog(operateName="单点登录") public ModelAndView singleLoginByUsername(HttpServletRequest request,HttpServletResponse response){ return doSingleLogin(request,response,"username"); } /** * 获取客户端请求信息,为了隔绝在server层使用request * @param request 请求对象 * @param clientInfo 客户端信息 */ private void wrapperBrowserInfo(RequestClientInfo clientInfo,HttpServletRequest request) { UserAgent userAgent = UserAgent.parseUserAgentString(request.getHeader("User-Agent")); if(StringUtils.isBlank(clientInfo.getIpaddress())){ //找IP地址 clientInfo.setIpaddress(getIpAddressFromRequest(request)); } if(userAgent !=null) { Browser browser = userAgent.getBrowser(); OperatingSystem os = userAgent.getOperatingSystem(); clientInfo.setOsversion(os != null ? os.getName() : ""); clientInfo.setBrowser(browser != null ? browser.getName() : "IE"); String version = ""; if (browser != null) { Version version1 = browser.getVersion(request.getHeader("User-Agent")); if (version1 != null) { version = version1.getVersion(); } } clientInfo.setBrowserversion(version); if (os != null) { clientInfo.setRequestType(os.getDeviceType().getName()); if (DeviceType.COMPUTER.getName().equals(clientInfo.getRequestType())) { clientInfo.setRequestType("browser"); } } Locale loc = Locale.getDefault(); clientInfo.setCountry(loc.getCountry()); clientInfo.setLanguage(loc.toLanguageTag()); Map map = System.getenv(); clientInfo.setMachine(map.get("COMPUTERNAME")); clientInfo.setOsUser(map.get("USERNAME")); } } /** * 从请求中获取ip地址,为了隔绝在server层使用request * @param request 请求对象 * @return ip地址,没有找到默认为127.0.0.1 */ private String getIpAddressFromRequest(HttpServletRequest request){ String ip = request.getHeader("X-Forwarded-For"); if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) { ip = request.getHeader("Proxy-Client-IP"); } if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) { ip = request.getHeader("WL-Proxy-Client-IP"); } if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) { ip = request.getHeader("HTTP_CLIENT_IP"); } if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) { ip = request.getHeader("HTTP_X_FORWARDED_FOR"); } if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) { ip = request.getRemoteAddr(); } if (ip == null || ip.length() == 0 || ip.indexOf("0:0:0:0:0:0:0:1") >-1) { //0:0:0:0:0:0:0:1是本机在访问 ip = "127.0.0.1"; } return ip; } /** * 获取用户的会话信息 * @return success为true表示获取成功,否则msg是错误信息,obj属性是获取的会话对象信息 */ @VciUnCheckRight @PostMapping("/getSessionInfo") @ResponseBody public BaseResult getSessionInfo(){ BaseResult json = new BaseResult<>(); json.setObj(WebThreadLocalUtil.getCurrentUserSessionInfoInThread()); if(json.getObj()!=null){ json.setSuccess(true); } return json; } /** * 执行退出 * @param request 请求对象 * @return success为true表示退出成功,前端不需要判断结果 */ @VciUnCheckRight @PostMapping("/logout") @ResponseBody public BaseResult logout(HttpServletRequest request){ String userToken = request.getHeader(TokenKeyConstant.USER_TOKEN_KEY); loginService.logout(userToken); return BaseResult.success(); } }