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();
}
}