LoginController.java 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424
  1. /**
  2. * Copyright &copy; 2015-2020 <a href="http://www.jeeplus.org/">JeePlus</a> All rights reserved.
  3. */
  4. package com.jeeplus.modules.sys.web;
  5. import java.io.IOException;
  6. import java.util.ArrayList;
  7. import java.util.Arrays;
  8. import java.util.List;
  9. import java.util.Map;
  10. import javax.servlet.http.Cookie;
  11. import javax.servlet.http.HttpServletRequest;
  12. import javax.servlet.http.HttpServletResponse;
  13. import com.jeeplus.common.utils.*;
  14. import com.jeeplus.modules.leader.org.entity.LeaderOrgNo;
  15. import com.jeeplus.modules.leader.org.service.LeaderOrgNoService;
  16. import com.jeeplus.modules.sys.entity.User;
  17. import com.jeeplus.modules.sys.mapper.UserMapper;
  18. import com.jeeplus.modules.sys.service.SystemService;
  19. import io.swagger.annotations.Api;
  20. import io.swagger.annotations.ApiImplicitParam;
  21. import io.swagger.annotations.ApiImplicitParams;
  22. import io.swagger.annotations.ApiOperation;
  23. import org.apache.shiro.authc.AuthenticationException;
  24. import org.apache.shiro.authc.SimpleAuthenticationInfo;
  25. import org.apache.shiro.authz.UnauthorizedException;
  26. import org.apache.shiro.authz.annotation.RequiresPermissions;
  27. import org.apache.shiro.util.ByteSource;
  28. import org.apache.shiro.web.util.SavedRequest;
  29. import org.apache.shiro.web.util.WebUtils;
  30. import org.springframework.beans.factory.annotation.Autowired;
  31. import org.springframework.stereotype.Controller;
  32. import org.springframework.ui.Model;
  33. import org.springframework.web.bind.annotation.PathVariable;
  34. import org.springframework.web.bind.annotation.RequestMapping;
  35. import org.springframework.web.bind.annotation.RequestMethod;
  36. import com.google.common.collect.Maps;
  37. import com.jeeplus.common.config.Global;
  38. import com.jeeplus.common.json.AjaxJson;
  39. import com.jeeplus.core.persistence.Page;
  40. import com.jeeplus.core.security.shiro.session.SessionDAO;
  41. import com.jeeplus.core.servlet.ValidateCodeServlet;
  42. import com.jeeplus.core.web.BaseController;
  43. import com.jeeplus.modules.sys.security.FormAuthenticationFilter;
  44. import com.jeeplus.modules.sys.security.SystemAuthorizingRealm.Principal;
  45. import com.jeeplus.modules.sys.utils.UserUtils;
  46. import org.springframework.web.bind.annotation.ResponseBody;
  47. import static org.jgroups.blocks.RpcDispatcher.getName;
  48. /**
  49. * 登录Controller
  50. * @author jeeplus
  51. * @version 2016-5-31
  52. */
  53. @Api(value = "LoginController", description = "登录控制器")
  54. @Controller
  55. public class LoginController extends BaseController{
  56. @Autowired
  57. private SessionDAO sessionDAO;
  58. @Autowired
  59. private UserMapper userMapper;
  60. @Autowired
  61. private LeaderOrgNoService orgNoService;
  62. /**
  63. * 管理登录
  64. * @throws IOException
  65. */
  66. @ResponseBody
  67. @ApiOperation(notes = "loginMobile", httpMethod = "POST", value = "用户登录")
  68. @ApiImplicitParams({@ApiImplicitParam(name = "username", value = "用户名", required = true, paramType = "query",dataType = "string"),
  69. @ApiImplicitParam(name = "password", value = "密码", required = true, paramType = "query",dataType = "string")})
  70. @RequestMapping(value = "${adminPath}/loginMobile")
  71. public AjaxJson loginMobile(String username,String password,HttpServletRequest request) {
  72. AjaxJson j = new AjaxJson();
  73. try {
  74. User user = userMapper.getByLoginName(new User(null, username));
  75. if (user == null) {
  76. j.setMsg("用户名错误");
  77. j.setSuccess(false);
  78. return j;
  79. } else {
  80. if (Global.NO.equals(user.getLoginFlag())) {
  81. j.setMsg("该帐号已禁止登录");
  82. j.setSuccess(false);
  83. return j;
  84. }
  85. if (StringUtils.isNotBlank(user.getType())) {
  86. j.setMsg("非系统用户禁止登录");
  87. j.setSuccess(false);
  88. return j;
  89. }
  90. boolean isValidate = SystemService.validatePassword(password, user.getPassword());
  91. if (isValidate) {
  92. j.setMsg("登录成功");
  93. String sessionId = request.getSession().getId();
  94. user.setSign(sessionId);
  95. List<String> parentNames = new ArrayList<String>();
  96. parentNames.add(orgNoService.get(user.getOffice().getId()).getName());
  97. String parentIds = user.getOffice().getParentIds();
  98. if (StringUtils.isNotBlank(parentIds)) {
  99. String[] ids = parentIds.split("\\,");
  100. for (int i = ids.length - 1; i >= 0; i--) {
  101. if (StringUtils.isNotBlank(ids[i]) && !ids[i].equals("0")) {
  102. LeaderOrgNo leaderOrgNo = orgNoService.get(ids[i]);
  103. if(leaderOrgNo == null){
  104. continue;
  105. }
  106. String id = orgNoService.get(ids[i]).getName();
  107. parentNames.add(id);
  108. }
  109. }
  110. }
  111. user.setParentNames(parentNames);
  112. //user.setParentNames(String.join(",",parentNames));
  113. request.setAttribute(sessionId, user);
  114. j.put("user", user);
  115. j.setSuccess(true);
  116. return j;
  117. } else {
  118. j.setSuccess(false);
  119. j.setMsg("密码错误");
  120. return j;
  121. }
  122. }
  123. }catch (Exception ex){
  124. ex.printStackTrace();
  125. j.setSuccess(false);
  126. j.setMsg("登录失败");
  127. return j;
  128. }
  129. }
  130. /**
  131. * 管理登录
  132. * @throws IOException
  133. */
  134. @ApiOperation(notes = "login", httpMethod = "POST", value = "用户登录")
  135. @ApiImplicitParams({@ApiImplicitParam(name = "username", value = "用户名", required = true, paramType = "query",dataType = "string"),
  136. @ApiImplicitParam(name = "password", value = "密码", required = true, paramType = "query",dataType = "string"),
  137. @ApiImplicitParam(name="mobileLogin",value = "接口标志",required = true, paramType = "query",dataType = "string")})
  138. @RequestMapping(value = "${adminPath}/login")
  139. public String login(HttpServletRequest request, HttpServletResponse response) throws IOException {
  140. Principal principal = UserUtils.getPrincipal();
  141. if (logger.isDebugEnabled()){
  142. logger.debug("login, active session size: {}", sessionDAO.getActiveSessions(false).size());
  143. }
  144. // 如果已登录,再次访问主页,则退出原账号。
  145. if (Global.TRUE.equals(Global.getConfig("notAllowRefreshIndex"))){
  146. CookieUtils.setCookie(response, "LOGINED", "false");
  147. }
  148. // 如果已经登录,则跳转到管理首页
  149. if(principal != null && !principal.isMobileLogin()){
  150. return "redirect:" + adminPath;
  151. }
  152. SavedRequest savedRequest = WebUtils.getSavedRequest(request);//获取跳转到login之前的URL
  153. // 如果是手机没有登录跳转到到login,则返回JSON字符串
  154. if(savedRequest != null){
  155. String queryStr = savedRequest.getQueryString();
  156. if( queryStr!=null &&( queryStr.contains("__ajax") || queryStr.contains("mobileLogin"))){
  157. AjaxJson j = new AjaxJson();
  158. j.setSuccess(false);
  159. j.setErrorCode("0");
  160. j.setMsg("没有登录!");
  161. return renderString(response, j);
  162. }
  163. }
  164. return "modules/sys/login/sysLogin";
  165. }
  166. /**
  167. * 登录失败,真正登录的POST请求由Filter完成
  168. */
  169. @RequestMapping(value = "${adminPath}/login", method = RequestMethod.POST)
  170. public String loginFail(HttpServletRequest request, HttpServletResponse response, Model model) {
  171. Principal principal = UserUtils.getPrincipal();
  172. // 如果已经登录,则跳转到管理首页
  173. if(principal != null){
  174. return "redirect:" + adminPath;
  175. }
  176. String username = WebUtils.getCleanParam(request, FormAuthenticationFilter.DEFAULT_USERNAME_PARAM);
  177. boolean rememberMe = WebUtils.isTrue(request, FormAuthenticationFilter.DEFAULT_REMEMBER_ME_PARAM);
  178. boolean mobile = WebUtils.isTrue(request, FormAuthenticationFilter.DEFAULT_MOBILE_PARAM);
  179. String exception = (String)request.getAttribute(FormAuthenticationFilter.DEFAULT_ERROR_KEY_ATTRIBUTE_NAME);
  180. String message = (String)request.getAttribute(FormAuthenticationFilter.DEFAULT_MESSAGE_PARAM);
  181. if (StringUtils.isBlank(message) || StringUtils.equals(message, "null")){
  182. message = "用户或密码错误, 请重试.";
  183. }
  184. model.addAttribute(FormAuthenticationFilter.DEFAULT_USERNAME_PARAM, username);
  185. model.addAttribute(FormAuthenticationFilter.DEFAULT_REMEMBER_ME_PARAM, rememberMe);
  186. model.addAttribute(FormAuthenticationFilter.DEFAULT_MOBILE_PARAM, mobile);
  187. model.addAttribute(FormAuthenticationFilter.DEFAULT_ERROR_KEY_ATTRIBUTE_NAME, exception);
  188. model.addAttribute(FormAuthenticationFilter.DEFAULT_MESSAGE_PARAM, message);
  189. if (logger.isDebugEnabled()){
  190. logger.debug("login fail, active session size: {}, message: {}, exception: {}",
  191. sessionDAO.getActiveSessions(false).size(), message, exception);
  192. }
  193. // 非授权异常,登录失败,验证码加1。
  194. if (!UnauthorizedException.class.getName().equals(exception)){
  195. model.addAttribute("isValidateCodeLogin", isValidateCodeLogin(username, true, false));
  196. }
  197. // 验证失败清空验证码
  198. request.getSession().setAttribute(ValidateCodeServlet.VALIDATE_CODE, IdGen.uuid());
  199. // 如果是手机登录,则返回JSON字符串
  200. if (mobile){
  201. AjaxJson j = new AjaxJson();
  202. j.setSuccess(false);
  203. j.setMsg(message);
  204. j.put("username", username);
  205. j.put("name","");
  206. j.put("mobileLogin", mobile);
  207. j.put("JSESSIONID", "");
  208. return renderString(response, j.getJsonStr());
  209. }
  210. return "modules/sys/login/sysLogin";
  211. }
  212. /**
  213. * 管理登录
  214. * @throws IOException
  215. */
  216. @RequestMapping(value = "${adminPath}/logout", method = RequestMethod.GET)
  217. public String logout(HttpServletRequest request, HttpServletResponse response, Model model) throws IOException {
  218. Principal principal = UserUtils.getPrincipal();
  219. // 如果已经登录,则跳转到管理首页
  220. if(principal != null){
  221. UserUtils.getSubject().logout();
  222. }
  223. // 如果是手机客户端退出跳转到login,则返回JSON字符串
  224. String ajax = request.getParameter("__ajax");
  225. if( ajax!=null){
  226. model.addAttribute("success", "1");
  227. model.addAttribute("msg", "退出成功");
  228. return renderString(response, model);
  229. }
  230. return "redirect:" + adminPath+"/login";
  231. }
  232. /**
  233. * 登录成功,进入管理首页
  234. */
  235. @RequiresPermissions("user")
  236. @RequestMapping(value = "${adminPath}")
  237. public String index(HttpServletRequest request, HttpServletResponse response) {
  238. Principal principal = UserUtils.getPrincipal();
  239. // 登录成功后,验证码计算器清零
  240. isValidateCodeLogin(principal.getLoginName(), false, true);
  241. if (logger.isDebugEnabled()){
  242. logger.debug("show index, active session size: {}", sessionDAO.getActiveSessions(false).size());
  243. }
  244. // 如果已登录,再次访问主页,则退出原账号。
  245. if (Global.TRUE.equals(Global.getConfig("notAllowRefreshIndex"))){
  246. String logined = CookieUtils.getCookie(request, "LOGINED");
  247. if (StringUtils.isBlank(logined) || "false".equals(logined)){
  248. CookieUtils.setCookie(response, "LOGINED", "true");
  249. }else if (StringUtils.equals(logined, "true")){
  250. UserUtils.getSubject().logout();
  251. return "redirect:" + adminPath + "/login";
  252. }
  253. }
  254. // 如果是手机登录,则返回JSON字符串
  255. if (principal.isMobileLogin()){
  256. if (request.getParameter("login") != null){
  257. return renderString(response, principal);
  258. }
  259. if (request.getParameter("index") != null){
  260. return "modules/sys/login/sysIndex";
  261. }
  262. return "redirect:" + adminPath + "/login";
  263. }
  264. if(UserUtils.getMenuList().size() == 0){
  265. return "modules/sys/login/noAuth";
  266. }else{
  267. // 默认风格
  268. String indexStyle ;
  269. if(MobileUtils.checkAgentIsMobile(request.getHeader("User-Agent"))){//如果是移动,默认使用左侧菜单,显示效果较好
  270. indexStyle = "ani";
  271. }else{//如果是pc端,默认使用jeeplus.properties中的配置项,jp横向菜单,ani左侧菜单
  272. indexStyle = Global.getDefaultTheme();
  273. }
  274. Cookie[] cookies = request.getCookies();
  275. for (Cookie cookie : cookies) {
  276. if (cookie == null || StringUtils.isEmpty(cookie.getName())) {
  277. continue;
  278. }
  279. if (cookie.getName().equalsIgnoreCase("style")) {
  280. indexStyle = cookie.getValue();
  281. }
  282. }
  283. // 要添加自己的风格,复制下面三行即可
  284. if (StringUtils.isNotEmpty(indexStyle)
  285. && indexStyle.equalsIgnoreCase("jp")) {
  286. return "modules/sys/login/sysIndex-jp";
  287. }
  288. return "modules/sys/login/sysIndex";
  289. }
  290. }
  291. /**
  292. * 切换风格
  293. */
  294. @ResponseBody
  295. @RequestMapping(value = "${adminPath}/style/{style}")
  296. public String getStyleInCookie(@PathVariable String style, HttpServletRequest request, HttpServletResponse response){
  297. if (StringUtils.isNotBlank(style)){
  298. CookieUtils.setCookie(response, "style", style);
  299. }else{
  300. style = CookieUtils.getCookie(request, "style");
  301. }
  302. return style;
  303. }
  304. /**
  305. * 获取主题颜色方案
  306. */
  307. @ResponseBody
  308. @RequestMapping(value = "${adminPath}/theme/{theme}")
  309. public String getThemeInCookie(@PathVariable String theme, HttpServletRequest request, HttpServletResponse response){
  310. if (StringUtils.isNotBlank(theme)){
  311. if(theme.contains("_")){
  312. String style = theme.split("_")[0];
  313. theme = theme.split("_")[1];
  314. if(style.equals("white")){
  315. CookieUtils.setCookie(response, "white", "theme-whbl");
  316. }else{
  317. CookieUtils.setCookie(response, "white", "");
  318. }
  319. CookieUtils.setCookie(response, "theme", theme);
  320. }else{
  321. CookieUtils.setCookie(response, "theme", theme);
  322. }
  323. }else{
  324. theme = CookieUtils.getCookie(request, "theme");
  325. }
  326. return theme;
  327. }
  328. /**
  329. * 是否启用tab
  330. */
  331. @RequestMapping(value = "${adminPath}/tab/{tab}")
  332. public String getTabInCookie(@PathVariable String tab, HttpServletRequest request, HttpServletResponse response){
  333. if (StringUtils.isNotBlank(tab)){
  334. CookieUtils.setCookie(response, "tab", tab);
  335. }else{
  336. tab = CookieUtils.getCookie(request, "tab");
  337. }
  338. return "redirect:"+request.getParameter("url");
  339. }
  340. /**
  341. * 是否是验证码登录
  342. * @param useruame 用户名
  343. * @param isFail 计数加1
  344. * @param clean 计数清零
  345. * @return
  346. */
  347. @SuppressWarnings("unchecked")
  348. public static boolean isValidateCodeLogin(String useruame, boolean isFail, boolean clean){
  349. Map<String, Integer> loginFailMap = (Map<String, Integer>)CacheUtils.get("loginFailMap");
  350. if (loginFailMap==null){
  351. loginFailMap = Maps.newHashMap();
  352. CacheUtils.put("loginFailMap", loginFailMap);
  353. }
  354. Integer loginFailNum = loginFailMap.get(useruame);
  355. if (loginFailNum==null){
  356. loginFailNum = 0;
  357. }
  358. if (isFail){
  359. loginFailNum++;
  360. loginFailMap.put(useruame, loginFailNum);
  361. }
  362. if (clean){
  363. loginFailMap.remove(useruame);
  364. }
  365. return loginFailNum >= 3;
  366. }
  367. /**
  368. * 首页
  369. * @throws IOException
  370. */
  371. @RequestMapping(value = "${adminPath}/home")
  372. public String home(HttpServletRequest request, HttpServletResponse response, Model model) throws IOException {
  373. return "modules/iim/calendar/myCalendar";
  374. //return "modules/sys/login/sysHome";
  375. }
  376. }