package com.landtool.lanbase.modules.sys.controller; import com.alibaba.druid.support.json.JSONUtils; import com.alibaba.fastjson.JSONObject; import com.fasterxml.jackson.databind.ser.std.StdKeySerializers.Default; import com.google.code.kaptcha.Constants; import com.google.code.kaptcha.Producer; import com.landtool.lanbase.common.Constant; import com.landtool.lanbase.common.annotation.LogLogininfo; import com.landtool.lanbase.common.exception.LanbaseException; import com.landtool.lanbase.common.shiro.ShiroToken; import com.landtool.lanbase.common.utils.CoderUtils; import com.landtool.lanbase.common.utils.HttpUtils; import com.landtool.lanbase.common.utils.Result; import com.landtool.lanbase.common.utils.ShiroUtils; import com.landtool.lanbase.config.SysTemPropertyConfig; import com.landtool.lanbase.modules.org.entity.OrgUser; import com.landtool.lanbase.modules.org.service.OrgUserService; import com.landtool.lanbase.modules.sys.redis.OnlineUserRedis; import com.landtool.lanbase.modules.sys.service.SysUserTokenService; import springfox.documentation.annotations.ApiIgnore; import org.apache.commons.io.IOUtils; import org.apache.shiro.SecurityUtils; import org.apache.shiro.session.Session; import org.apache.shiro.session.mgt.eis.MemorySessionDAO; import org.apache.shiro.session.mgt.eis.SessionDAO; import org.apache.shiro.subject.SimplePrincipalCollection; import org.apache.shiro.subject.Subject; import org.apache.shiro.subject.support.DefaultSubjectContext; import org.apache.shiro.util.StringUtils; import org.apache.shiro.web.mgt.DefaultWebSecurityManager; import org.apache.shiro.web.session.mgt.DefaultWebSessionManager; import org.apache.shiro.web.util.SavedRequest; import org.apache.shiro.web.util.WebUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.ResponseBody; import org.springframework.web.bind.annotation.RestController; import org.springframework.web.servlet.ModelAndView; import org.springframework.beans.factory.annotation.Value; import javax.imageio.ImageIO; import javax.servlet.ServletException; import javax.servlet.ServletOutputStream; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.awt.image.BufferedImage; import java.io.IOException; import java.net.URLEncoder; import java.util.Collection; import java.util.Map; /** * @author lanbase * @Description: TODO(登录相关) * @date 2017-6-23 15:07 */ @RestController @ApiIgnore() public class SysLoginController extends AbstractController { private Logger logger = LoggerFactory.getLogger(getClass()); @Autowired private Producer producer; @Autowired private OrgUserService orgUserService; @Autowired private SysUserTokenService sysUserTokenService; @Autowired private SysTemPropertyConfig sysConfig; @Autowired private OnlineUserRedis onlineUserRedis; /** * 首页 * @param request * @param response * @throws IOException */ @RequestMapping(value = "/", method = RequestMethod.GET) public void hutaiadmin(HttpServletRequest request, HttpServletResponse response) throws IOException { response.sendRedirect("/lanwebapp/admin/index.html"); } @RequestMapping("/captcha.jpg") public void captcha(HttpServletResponse response) throws ServletException, IOException { response.setHeader("Cache-Control", "no-store, no-cache"); response.setContentType("image/jpeg"); // 生成文字验证码 String text = producer.createText(); // 生成图片验证码 BufferedImage image = producer.createImage(text); // 保存到shiro session ShiroUtils.setSessionAttribute(Constants.KAPTCHA_SESSION_KEY, text); ServletOutputStream out = response.getOutputStream(); ImageIO.write(image, "jpg", out); IOUtils.closeQuietly(out); } /** * 获取登录错误次数 */ @RequestMapping(value = "/sys/getLoginErrorTimes", method = RequestMethod.GET) public Result getLoginErrorTimes() { Object errorTimes = ShiroUtils.getSessionAttribute(Constant.LOGIN_ERROR_TIMES); return Result.ok().put("errorTimes", errorTimes); } /** * oa门户反验证 获取地址上的validatename,调用反验证接口获取结果,为true,则允许登录 */ public JSONObject portallogin(HttpServletRequest request) { String result=""; String querystring=request.getQueryString(); String username=""; if(querystring!=null){ String par[] = querystring.split("&"); for (int i = 0; i < par.length; i++) { String a = par[i].split("=")[0]; String v = par[i].split("=")[1]; if(a.equals("validateNumber")){ String validateurl="http://192.168.4.50/services/PortalLoginService/ValidLoginUser?validateNumber="+v; try { result= HttpUtils.get(validateurl); } catch (Exception e) { logger.info(result); e.printStackTrace(); } } if(a.equals("userName")){ username=v; } } int start= result.indexOf(""); int end=result.indexOf(""); if(start!=-1&&end!=-1){ JSONObject json= JSONObject.parseObject(result.substring(start+11,end)); json.put("username", username); return json; } } return null; } /** * 登录 */ @LogLogininfo("登录") @RequestMapping(value = "/sys/login", method = RequestMethod.POST) public Result login(String username, String password, String captcha) throws IOException { Object _login_errors = ShiroUtils.getSessionAttribute(Constant.LOGIN_ERROR_TIMES); if (_login_errors == null) { _login_errors = 0; } long errorTimes = Long.valueOf(_login_errors.toString()); // 用户信息 OrgUser user = orgUserService.queryByUserName(username); // 账号不存在 if (user == null) { ShiroUtils.setSessionAttribute(Constant.LOGIN_ERROR_TIMES, ++errorTimes); return Result.error("账号不存在").put("errorTimes", errorTimes); } // 密码错误 try { if (!user.getPassword().equals(CoderUtils.lantuEncryptMD5(password))) { ShiroUtils.setSessionAttribute(Constant.LOGIN_ERROR_TIMES, ++errorTimes); return Result.error("密码不正确").put("errorTimes", errorTimes); } } catch (Exception e) { e.printStackTrace(); } // 验证码 if (errorTimes >= 3) { String kaptcha = getKaptcha(Constants.KAPTCHA_SESSION_KEY); if (!captcha.equalsIgnoreCase(kaptcha)) { ShiroUtils.setSessionAttribute(Constant.LOGIN_ERROR_TIMES, ++errorTimes); return Result.error("验证码不正确").put("errorTimes", errorTimes); } } // 账号锁定 if (Constant.UserStatus.DISABLE.getValue() == user.getUserstatus()) { ShiroUtils.setSessionAttribute(Constant.LOGIN_ERROR_TIMES, ++errorTimes); return Result.error("账号已被锁定,请联系管理员").put("errorTimes", errorTimes); } // 生成token,并保存到数据库 Map result = sysUserTokenService.createToken(user.getUserid()); Result r = Result.ok().put(result); return r; } private String getLoginNamefromXml(HttpServletRequest request) throws Exception { String username = ""; // 判断ticket // String CASHOST = "https://www.lt.com:8443/cas/"; String CasHost = sysConfig.getCasHost();//https://cas.nmsmp.com/cas/ String loginUrl = sysConfig.getLoginUrl(); //http://127.0.0.1:8082/login String ticket = request.getParameter("ticket"); if (!org.springframework.util.StringUtils.isEmpty(ticket)) { String server = getOldQueryString(request); String url=CasHost.replace("https", "http"); String validateurl = url + "serviceValidate?ticket="+ticket +"&service=" +loginUrl +"?oldurl="+ URLEncoder.encode(server); ; logger.debug("2----ServiceValidate:" + validateurl); String casxml; casxml = HttpUtils.get(validateurl); logger.debug(casxml); Integer index = casxml.indexOf(""); Integer end = casxml.indexOf(""); if (index > 0) { username = casxml.substring(index + 10, end); } } return username; } @LogLogininfo("登录") @RequestMapping(value = "/index", method = RequestMethod.GET) @ResponseBody public void index(HttpServletRequest request, HttpServletResponse response) throws IOException { String username = request.getRemoteUser(); response.setCharacterEncoding("utf-8"); response.setContentType("text/plain"); response.getWriter().write(username + "登陆成功!"); } /** * CAS登陆成功后调用此方法创建本系统的token * @param request * @param response * @return * @throws Exception */ @LogLogininfo("登录") @RequestMapping(value = "/login", method = RequestMethod.GET) public void login(HttpServletRequest request, HttpServletResponse response) throws Exception { String username = request.getRemoteUser(); if (StringUtils.hasText(username)) {// 已经登录shiro String oldUrl = getOldParameterPath(request); WebUtils.issueRedirect(request, response, oldUrl); } else { username = getLoginNamefromXml(request); if (StringUtils.hasText(username)) { OrgUser user = orgUserService.queryByUserName(username); // 账号不存在 if (user == null) { response.getWriter().write("[" + username + "]账号不存在或未注册到系统"); return; } Subject subject = SecurityUtils.getSubject(); ShiroToken shiroToken = new ShiroToken(username, true); subject.login(shiroToken); onlineUserRedis.saveOnlineUser(username,subject.getSession()); String oldUrl = getOldQueryString(request); logger.debug("3----RedirectOldurl:" + oldUrl); WebUtils.issueRedirect(request, response, oldUrl); } else { String CasHost = sysConfig.getCasHost();//https://cas.nmsmp.com/cas/ String loginUrl = sysConfig.getLoginUrl(); //http://127.0.0.1:8082/login String oldurl = getOldSessionPath(request); if (StringUtils.hasText(oldurl)) { CasHost += "login?service=" +loginUrl+"?oldurl="+ URLEncoder.encode(oldurl); } logger.debug("1----RedirectCasloginUrl:" + CasHost); response.sendRedirect(CasHost);// 用户名不存在跳转回登录页面 } } } private String getOldQueryString(HttpServletRequest request) { String server = request.getQueryString(); String ticket = request.getParameter("ticket"); if (!org.springframework.util.StringUtils.isEmpty(ticket)) { server=server.replace("ticket="+ticket , ""); if(server.endsWith("&"))server=server.substring(0,server.length()-1); } server=server.replace("oldurl=" , ""); return server; } /*** * 获取原始访问路径 * * @return */ private String getOldParameterPath(HttpServletRequest request) { String oldUrl = request.getParameter("oldurl"); oldUrl = (oldUrl == null) ? "/" : oldUrl; return oldUrl; } /*** * 获取原始访问路径 * * @return */ private String getOldSessionPath(HttpServletRequest request) { String oldurl = getOldParameterPath(request); if(oldurl=="/") { Subject subject = SecurityUtils.getSubject(); Session session = subject.getSession(); SavedRequest req = (SavedRequest) session.getAttribute(WebUtils.SAVED_REQUEST_KEY); oldurl = (req == null) ? "" : req.getRequestUrl(); } return oldurl; } /** * CAS登陆成功后调用此方法创建本系统的token 返回jsonp * @param request * @param response * @return */ @LogLogininfo("登录") @RequestMapping(value = "/sys/caslogin2", method = RequestMethod.GET) @ResponseBody public String caslogin2(HttpServletRequest request, HttpServletResponse response) { String callbackFunName = request.getParameter("callback"); // js回调函数名称 if (callbackFunName == null || callbackFunName.isEmpty()) { callbackFunName = "casloginCallback"; } response.setCharacterEncoding("utf-8"); response.setContentType("text/plain"); return "";// getJsonp(caslogin(request, response), callbackFunName); } /** * 转化为jsonp字符串 * @param map * @param callbackFunName * @return */ private String getJsonp(Map map, String callbackFunName) { String jsonp = JSONUtils.toJSONString(map); return callbackFunName + "(" + jsonp + ")"; } /** * 退出 * @throws IOException */ @LogLogininfo("登出") @RequestMapping(value = "/logout") public void logout(HttpServletRequest request, HttpServletResponse response) throws IOException { Subject subject = SecurityUtils.getSubject(); onlineUserRedis.cleanLogoutUser(subject.getSession()); subject.logout(); String CasHost= sysConfig.getCasHost(); String logoutUrl=CasHost+"logout?service="+CasHost+"login"; WebUtils.issueRedirect(request, response, logoutUrl); //sysUserTokenService.logout(getUserId()); //return Result.ok(); } /** * 从session中获取记录的验证码 */ private String getKaptcha(String key) { Object kaptcha = ShiroUtils.getSessionAttribute(key); if (kaptcha == null) { throw new LanbaseException("验证码已失效"); } ShiroUtils.getSession().removeAttribute(key); return kaptcha.toString(); } /** * 从session中获取记录的验证码 */ private Session getSessionByUsername(String username) { DefaultWebSecurityManager securityManager=(DefaultWebSecurityManager) SecurityUtils.getSecurityManager(); DefaultWebSessionManager sessionManager=(DefaultWebSessionManager) securityManager.getSessionManager(); Collection sessions=sessionManager.getSessionDAO().getActiveSessions(); Object attribute; String user; Session ses = null; for(Session session:sessions){ attribute=session.getAttribute(DefaultSubjectContext.PRINCIPALS_SESSION_KEY); user=((SimplePrincipalCollection) attribute).toString(); if(user.equals(username)){ ses=session; session.stop(); break; } } return ses; } /** * 退出 * @throws IOException */ @LogLogininfo("登出") @RequestMapping(value = "/tick") public void tickSomeOneDown(HttpServletRequest request, HttpServletResponse response) throws IOException { Subject subject = SecurityUtils.getSubject(); onlineUserRedis.cleanLogoutUser(subject.getSession()); subject.logout(); String CasHost= sysConfig.getCasHost(); String logoutUrl=CasHost+"logout?service="+CasHost+"login"; WebUtils.issueRedirect(request, response, logoutUrl); //sysUserTokenService.logout(getUserId()); //return Result.ok(); } }