/** * Copyright © 2015-2020 JeePlus All rights reserved. */ package com.jeeplus.modules.sys.web; import java.io.IOException; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.Map; import javax.servlet.http.Cookie; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import com.jeeplus.common.utils.*; import com.jeeplus.modules.leader.org.entity.LeaderOrgNo; import com.jeeplus.modules.leader.org.service.LeaderOrgNoService; import com.jeeplus.modules.sys.entity.User; import com.jeeplus.modules.sys.mapper.UserMapper; import com.jeeplus.modules.sys.service.SystemService; import io.swagger.annotations.Api; import io.swagger.annotations.ApiImplicitParam; import io.swagger.annotations.ApiImplicitParams; import io.swagger.annotations.ApiOperation; import org.apache.shiro.authc.AuthenticationException; import org.apache.shiro.authc.SimpleAuthenticationInfo; import org.apache.shiro.authz.UnauthorizedException; import org.apache.shiro.authz.annotation.RequiresPermissions; import org.apache.shiro.util.ByteSource; import org.apache.shiro.web.util.SavedRequest; import org.apache.shiro.web.util.WebUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import com.google.common.collect.Maps; import com.jeeplus.common.config.Global; import com.jeeplus.common.json.AjaxJson; import com.jeeplus.core.persistence.Page; import com.jeeplus.core.security.shiro.session.SessionDAO; import com.jeeplus.core.servlet.ValidateCodeServlet; import com.jeeplus.core.web.BaseController; import com.jeeplus.modules.sys.security.FormAuthenticationFilter; import com.jeeplus.modules.sys.security.SystemAuthorizingRealm.Principal; import com.jeeplus.modules.sys.utils.UserUtils; import org.springframework.web.bind.annotation.ResponseBody; import static org.jgroups.blocks.RpcDispatcher.getName; /** * 登录Controller * @author jeeplus * @version 2016-5-31 */ @Api(value = "LoginController", description = "登录控制器") @Controller public class LoginController extends BaseController{ @Autowired private SessionDAO sessionDAO; @Autowired private UserMapper userMapper; @Autowired private LeaderOrgNoService orgNoService; /** * 管理登录 * @throws IOException */ @ResponseBody @ApiOperation(notes = "loginMobile", httpMethod = "POST", value = "用户登录") @ApiImplicitParams({@ApiImplicitParam(name = "username", value = "用户名", required = true, paramType = "query",dataType = "string"), @ApiImplicitParam(name = "password", value = "密码", required = true, paramType = "query",dataType = "string")}) @RequestMapping(value = "${adminPath}/loginMobile") public AjaxJson loginMobile(String username,String password,HttpServletRequest request) { AjaxJson j = new AjaxJson(); try { User user = userMapper.getByLoginName(new User(null, username)); if (user == null) { j.setMsg("用户名错误"); j.setSuccess(false); return j; } else { if (Global.NO.equals(user.getLoginFlag())) { j.setMsg("该帐号已禁止登录"); j.setSuccess(false); return j; } if (StringUtils.isNotBlank(user.getType())) { j.setMsg("非系统用户禁止登录"); j.setSuccess(false); return j; } boolean isValidate = SystemService.validatePassword(password, user.getPassword()); if (isValidate) { j.setMsg("登录成功"); String sessionId = request.getSession().getId(); user.setSign(sessionId); List parentNames = new ArrayList(); parentNames.add(orgNoService.get(user.getOffice().getId()).getName()); String parentIds = user.getOffice().getParentIds(); if (StringUtils.isNotBlank(parentIds)) { String[] ids = parentIds.split("\\,"); for (int i = ids.length - 1; i >= 0; i--) { if (StringUtils.isNotBlank(ids[i]) && !ids[i].equals("0")) { LeaderOrgNo leaderOrgNo = orgNoService.get(ids[i]); if(leaderOrgNo == null){ continue; } String id = orgNoService.get(ids[i]).getName(); parentNames.add(id); } } } user.setParentNames(parentNames); //user.setParentNames(String.join(",",parentNames)); request.setAttribute(sessionId, user); j.put("user", user); j.setSuccess(true); return j; } else { j.setSuccess(false); j.setMsg("密码错误"); return j; } } }catch (Exception ex){ ex.printStackTrace(); j.setSuccess(false); j.setMsg("登录失败"); return j; } } /** * 管理登录 * @throws IOException */ @ApiOperation(notes = "login", httpMethod = "POST", value = "用户登录") @ApiImplicitParams({@ApiImplicitParam(name = "username", value = "用户名", required = true, paramType = "query",dataType = "string"), @ApiImplicitParam(name = "password", value = "密码", required = true, paramType = "query",dataType = "string"), @ApiImplicitParam(name="mobileLogin",value = "接口标志",required = true, paramType = "query",dataType = "string")}) @RequestMapping(value = "${adminPath}/login") public String login(HttpServletRequest request, HttpServletResponse response) throws IOException { Principal principal = UserUtils.getPrincipal(); if (logger.isDebugEnabled()){ logger.debug("login, active session size: {}", sessionDAO.getActiveSessions(false).size()); } // 如果已登录,再次访问主页,则退出原账号。 if (Global.TRUE.equals(Global.getConfig("notAllowRefreshIndex"))){ CookieUtils.setCookie(response, "LOGINED", "false"); } // 如果已经登录,则跳转到管理首页 if(principal != null && !principal.isMobileLogin()){ return "redirect:" + adminPath; } SavedRequest savedRequest = WebUtils.getSavedRequest(request);//获取跳转到login之前的URL // 如果是手机没有登录跳转到到login,则返回JSON字符串 if(savedRequest != null){ String queryStr = savedRequest.getQueryString(); if( queryStr!=null &&( queryStr.contains("__ajax") || queryStr.contains("mobileLogin"))){ AjaxJson j = new AjaxJson(); j.setSuccess(false); j.setErrorCode("0"); j.setMsg("没有登录!"); return renderString(response, j); } } return "modules/sys/login/sysLogin"; } /** * 登录失败,真正登录的POST请求由Filter完成 */ @RequestMapping(value = "${adminPath}/login", method = RequestMethod.POST) public String loginFail(HttpServletRequest request, HttpServletResponse response, Model model) { Principal principal = UserUtils.getPrincipal(); // 如果已经登录,则跳转到管理首页 if(principal != null){ return "redirect:" + adminPath; } String username = WebUtils.getCleanParam(request, FormAuthenticationFilter.DEFAULT_USERNAME_PARAM); boolean rememberMe = WebUtils.isTrue(request, FormAuthenticationFilter.DEFAULT_REMEMBER_ME_PARAM); boolean mobile = WebUtils.isTrue(request, FormAuthenticationFilter.DEFAULT_MOBILE_PARAM); String exception = (String)request.getAttribute(FormAuthenticationFilter.DEFAULT_ERROR_KEY_ATTRIBUTE_NAME); String message = (String)request.getAttribute(FormAuthenticationFilter.DEFAULT_MESSAGE_PARAM); if (StringUtils.isBlank(message) || StringUtils.equals(message, "null")){ message = "用户或密码错误, 请重试."; } model.addAttribute(FormAuthenticationFilter.DEFAULT_USERNAME_PARAM, username); model.addAttribute(FormAuthenticationFilter.DEFAULT_REMEMBER_ME_PARAM, rememberMe); model.addAttribute(FormAuthenticationFilter.DEFAULT_MOBILE_PARAM, mobile); model.addAttribute(FormAuthenticationFilter.DEFAULT_ERROR_KEY_ATTRIBUTE_NAME, exception); model.addAttribute(FormAuthenticationFilter.DEFAULT_MESSAGE_PARAM, message); if (logger.isDebugEnabled()){ logger.debug("login fail, active session size: {}, message: {}, exception: {}", sessionDAO.getActiveSessions(false).size(), message, exception); } // 非授权异常,登录失败,验证码加1。 if (!UnauthorizedException.class.getName().equals(exception)){ model.addAttribute("isValidateCodeLogin", isValidateCodeLogin(username, true, false)); } // 验证失败清空验证码 request.getSession().setAttribute(ValidateCodeServlet.VALIDATE_CODE, IdGen.uuid()); // 如果是手机登录,则返回JSON字符串 if (mobile){ AjaxJson j = new AjaxJson(); j.setSuccess(false); j.setMsg(message); j.put("username", username); j.put("name",""); j.put("mobileLogin", mobile); j.put("JSESSIONID", ""); return renderString(response, j.getJsonStr()); } return "modules/sys/login/sysLogin"; } /** * 管理登录 * @throws IOException */ @RequestMapping(value = "${adminPath}/logout", method = RequestMethod.GET) public String logout(HttpServletRequest request, HttpServletResponse response, Model model) throws IOException { Principal principal = UserUtils.getPrincipal(); // 如果已经登录,则跳转到管理首页 if(principal != null){ UserUtils.getSubject().logout(); } // 如果是手机客户端退出跳转到login,则返回JSON字符串 String ajax = request.getParameter("__ajax"); if( ajax!=null){ model.addAttribute("success", "1"); model.addAttribute("msg", "退出成功"); return renderString(response, model); } return "redirect:" + adminPath+"/login"; } /** * 登录成功,进入管理首页 */ @RequiresPermissions("user") @RequestMapping(value = "${adminPath}") public String index(HttpServletRequest request, HttpServletResponse response) { Principal principal = UserUtils.getPrincipal(); // 登录成功后,验证码计算器清零 isValidateCodeLogin(principal.getLoginName(), false, true); if (logger.isDebugEnabled()){ logger.debug("show index, active session size: {}", sessionDAO.getActiveSessions(false).size()); } // 如果已登录,再次访问主页,则退出原账号。 if (Global.TRUE.equals(Global.getConfig("notAllowRefreshIndex"))){ String logined = CookieUtils.getCookie(request, "LOGINED"); if (StringUtils.isBlank(logined) || "false".equals(logined)){ CookieUtils.setCookie(response, "LOGINED", "true"); }else if (StringUtils.equals(logined, "true")){ UserUtils.getSubject().logout(); return "redirect:" + adminPath + "/login"; } } // 如果是手机登录,则返回JSON字符串 if (principal.isMobileLogin()){ if (request.getParameter("login") != null){ return renderString(response, principal); } if (request.getParameter("index") != null){ return "modules/sys/login/sysIndex"; } return "redirect:" + adminPath + "/login"; } if(UserUtils.getMenuList().size() == 0){ return "modules/sys/login/noAuth"; }else{ // 默认风格 String indexStyle ; if(MobileUtils.checkAgentIsMobile(request.getHeader("User-Agent"))){//如果是移动,默认使用左侧菜单,显示效果较好 indexStyle = "ani"; }else{//如果是pc端,默认使用jeeplus.properties中的配置项,jp横向菜单,ani左侧菜单 indexStyle = Global.getDefaultTheme(); } Cookie[] cookies = request.getCookies(); for (Cookie cookie : cookies) { if (cookie == null || StringUtils.isEmpty(cookie.getName())) { continue; } if (cookie.getName().equalsIgnoreCase("style")) { indexStyle = cookie.getValue(); } } // 要添加自己的风格,复制下面三行即可 if (StringUtils.isNotEmpty(indexStyle) && indexStyle.equalsIgnoreCase("jp")) { return "modules/sys/login/sysIndex-jp"; } return "modules/sys/login/sysIndex"; } } /** * 切换风格 */ @ResponseBody @RequestMapping(value = "${adminPath}/style/{style}") public String getStyleInCookie(@PathVariable String style, HttpServletRequest request, HttpServletResponse response){ if (StringUtils.isNotBlank(style)){ CookieUtils.setCookie(response, "style", style); }else{ style = CookieUtils.getCookie(request, "style"); } return style; } /** * 获取主题颜色方案 */ @ResponseBody @RequestMapping(value = "${adminPath}/theme/{theme}") public String getThemeInCookie(@PathVariable String theme, HttpServletRequest request, HttpServletResponse response){ if (StringUtils.isNotBlank(theme)){ if(theme.contains("_")){ String style = theme.split("_")[0]; theme = theme.split("_")[1]; if(style.equals("white")){ CookieUtils.setCookie(response, "white", "theme-whbl"); }else{ CookieUtils.setCookie(response, "white", ""); } CookieUtils.setCookie(response, "theme", theme); }else{ CookieUtils.setCookie(response, "theme", theme); } }else{ theme = CookieUtils.getCookie(request, "theme"); } return theme; } /** * 是否启用tab */ @RequestMapping(value = "${adminPath}/tab/{tab}") public String getTabInCookie(@PathVariable String tab, HttpServletRequest request, HttpServletResponse response){ if (StringUtils.isNotBlank(tab)){ CookieUtils.setCookie(response, "tab", tab); }else{ tab = CookieUtils.getCookie(request, "tab"); } return "redirect:"+request.getParameter("url"); } /** * 是否是验证码登录 * @param useruame 用户名 * @param isFail 计数加1 * @param clean 计数清零 * @return */ @SuppressWarnings("unchecked") public static boolean isValidateCodeLogin(String useruame, boolean isFail, boolean clean){ Map loginFailMap = (Map)CacheUtils.get("loginFailMap"); if (loginFailMap==null){ loginFailMap = Maps.newHashMap(); CacheUtils.put("loginFailMap", loginFailMap); } Integer loginFailNum = loginFailMap.get(useruame); if (loginFailNum==null){ loginFailNum = 0; } if (isFail){ loginFailNum++; loginFailMap.put(useruame, loginFailNum); } if (clean){ loginFailMap.remove(useruame); } return loginFailNum >= 3; } /** * 首页 * @throws IOException */ @RequestMapping(value = "${adminPath}/home") public String home(HttpServletRequest request, HttpServletResponse response, Model model) throws IOException { return "modules/iim/calendar/myCalendar"; //return "modules/sys/login/sysHome"; } }