/* * Copyright (c) 2008-2016 Computer Network Information Center (CNIC), Chinese Academy of Sciences. * * This file is part of Duckling project. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * */ package cn.vlabs.umt.ui.servlet.login; import java.io.File; import java.io.IOException; import java.io.UnsupportedEncodingException; import java.net.URLEncoder; import java.util.Date; import java.util.Map; import javax.servlet.RequestDispatcher; import javax.servlet.ServletException; import javax.servlet.http.Cookie; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; import org.apache.commons.lang.StringUtils; import org.apache.commons.lang.time.DateFormatUtils; import org.apache.commons.lang.time.DateUtils; import org.springframework.beans.factory.BeanFactory; import cn.vlabs.commons.principal.UserPrincipalV7; import cn.vlabs.duckling.common.transmission.SignedEnvelope; import cn.vlabs.duckling.common.transmission.UserCredentialEnvelope; import cn.vlabs.duckling.common.transmission.UserCredentialEnvelopeV7; import cn.vlabs.duckling.common.util.Base64Util; import cn.vlabs.umt.common.util.CommonUtils; import cn.vlabs.umt.common.util.RequestUtil; import cn.vlabs.umt.services.account.IAccountService; import cn.vlabs.umt.services.auth.IAuthService; import cn.vlabs.umt.services.auth.ThirdPartyAuth; import cn.vlabs.umt.services.role.RoleService; import cn.vlabs.umt.services.role.UMTRole; import cn.vlabs.umt.services.session.SessionService; import cn.vlabs.umt.services.session.SessionUtils; import cn.vlabs.umt.services.site.ApplicationNotFound; import cn.vlabs.umt.services.user.Credential; import cn.vlabs.umt.services.user.LoginService; import cn.vlabs.umt.services.user.bean.BindInfo; import cn.vlabs.umt.services.user.bean.CookieCredential; import cn.vlabs.umt.services.user.bean.LoginInfo; import cn.vlabs.umt.services.user.bean.LoginNameInfo; import cn.vlabs.umt.services.user.bean.ThirdPartyCredential; import cn.vlabs.umt.services.user.bean.User; import cn.vlabs.umt.services.user.bean.UsernamePasswordCredential; import cn.vlabs.umt.services.user.utils.ServiceFactory; import cn.vlabs.umt.ui.Attributes; import cn.vlabs.umt.ui.UMTContext; public abstract class LoginMethod { private IAuthService authService; private IAccountService acct; public LoginMethod(BeanFactory factory) { this.factory = factory; acct = (IAccountService) factory.getBean("AccountService"); authService = factory.getBean(IAuthService.class); } private void login(HttpServletRequest request, int uid, String authBy) { String loginType = null; if (CommonUtils.isNull(authBy)) { loginType = User.USER_TYPE_UMT; } else { loginType = authBy; } acct.login(loginType, null, uid, RequestUtil.getRemoteIP(request), new Date(), request.getHeader("User-Agent"), ""); } public void doLogin(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { String act = request.getParameter("act"); String type = request.getParameter("type"); if (BindInfo.isThirdParty(type) || authService.existAuth(type)) { insertThirdBind(request); } try { boolean result = loginByDeputy(request, response); if (!result && "Validate".equals(act)) { loginByInput(request, response); } else if (!result) { if (!loginBySession(request, response) && !loginByCookie(request, response)) { // 记录登录的应用 request.setAttribute(Attributes.APP_NAME, request.getParameter(Attributes.APP_NAME)); HttpSession session=request.getSession(); String requireValid=(String) session.getAttribute("requireValid"); if(StringUtils.isNotBlank(requireValid)&&StringUtils.equals(requireValid, "true")){ request.setAttribute("showValidCode", "true"); } redirectToLogin(request, response); } } } catch (ApplicationNotFound e) { request.setAttribute("error", e); doForward("/error.jsp", request, response); } } private boolean insertThirdBind(HttpServletRequest request) { String openId = SessionUtils.getSessionVar(request, Attributes.THIRDPARTY_OPEN_ID); if (!CommonUtils.isNull(openId)) { User user = ServiceFactory.getUserService(request).getUserByOpenid(openId, SessionUtils.getSessionVar(request, Attributes.THIRDPARTY_TYPE), SessionUtils.getSessionVar(request, Attributes.THIRDPARTY_URL)); if (user != null) { request.setAttribute("username", user.getCstnetId()); request.setAttribute("password", openId); return true; } } return false; } private String getThemedJSP(HttpServletRequest request, String jsp) { String theme = request.getParameter("theme"); if (CommonUtils.isNull(theme)) { theme = (String) request.getSession().getAttribute("theme"); } if (theme != null) { String calcedPath = "/themes/" + theme + jsp; File f = new File(request.getSession().getServletContext().getRealPath(calcedPath)); if (f.exists() && f.isFile()) { return calcedPath; } } return jsp; } protected abstract void redirectToLogin(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException; protected abstract boolean checkValidateCode(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException; protected abstract void onWrongPassword(HttpServletRequest request, HttpServletResponse response,String wrongType) throws ServletException, IOException; private boolean loginByDeputy(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { String loginByDeputy = request.getParameter("loginByDeputy"); if (loginByDeputy != null) { Map<String, String> siteInfo = SessionUtils.getSiteInfo(request); String username = request.getParameter("username"); String password = request.getParameter("password"); String authBy = request.getParameter("authBy"); if (StringUtils.isEmpty(password)) { password = ""; } LoginInfo info = this.checkUser(username, password, authBy); User prins = (info != null) ? info.getUser() : null; if (prins == null) { siteInfo.put(Attributes.APP_DEPUTY_LOGIN_RESULT_KEY, "error"); } else { siteInfo.put(Attributes.APP_DEPUTY_LOGIN_RESULT_KEY, "success"); generateSsoCookie(response, request, info); this.saveThirdPartyCredential(request, authBy, username, password); generateAutoFill(response, request, info); } sendTicket(prins, siteInfo, request, response); return true; } return false; } private LoginInfo checkUser(String username, String password, String authBy) { LoginService lservice = (LoginService) factory.getBean(LoginService.BEAN_ID); String userName= username.toLowerCase(); Credential credential = null; if (authBy == null || User.USER_TYPE_UMT.equals(authBy) || User.USER_TYPE_CORE_MAIL.equals(authBy) || User.USER_TYPE_MAIL_AND_UMT.equals(authBy)) { credential = new UsernamePasswordCredential(userName, password); } // 比如新浪,扣扣,smtp之类的 else { credential = new ThirdPartyCredential(userName, password, authBy); } LoginInfo prins = lservice.loginAndReturnPasswordType(credential); return prins; } private void loginByInput(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException, ApplicationNotFound { String appnamePara = request.getParameter(Attributes.APP_NAME); HttpSession session = request.getSession(); // 貌似appnamePara不为空即为第三方登陆,mirror除外 if (CommonUtils.isNull(appnamePara)) { appnamePara = (String) session.getAttribute(Attributes.APP_NAME); } request.setAttribute(Attributes.APP_NAME, appnamePara); String authBy = request.getParameter("authBy"); if (CommonUtils.isNull(authBy)) { authBy = (String) session.getAttribute("authBy"); } request.setAttribute("authBy", authBy); if (!checkValidateCode(request, response)) { return; } // 检查用户名 String username = request.getParameter("username"); if (CommonUtils.isNull(username)) { username = (String) request.getAttribute("username"); } String password = request.getParameter("password"); if (CommonUtils.isNull(password)) { password = (String) request.getAttribute("password"); } if (StringUtils.isEmpty(username)) { request.setAttribute("username", username); onWrongPassword(request, response,"true"); return; } LoginInfo info = this.checkUser(username, password, authBy); User prins = (info != null) ? info.getUser() : null; if (prins == null) { request.setAttribute("username", username); onWrongPassword(request, response,info.getValidateResult()); return; } // 保存第三用户凭证信息 saveThirdPartyCredential(request, authBy, username, password); // 保存登录信息 UMTContext.saveUser(session, info); // 拦截,如果用户为未激活用户,不能让他过去 Map<String, String> siteInfo = SessionUtils.getSiteInfo(request); User user = SessionUtils.getUser(request); login(request, user.getId(), authBy); LoginNameInfo nameInfo = info.getLoginNameInfo(); ThirdPartyAuth otherUmt=authService.find(authBy); info.setRequireUpgrade(otherUmt!=null || BindInfo.TYPE_QQ.equals(authBy)); boolean isThirdBind = BindInfo.isThirdParty(authBy) || otherUmt!=null; if (!isThirdBind || CommonUtils.isNull(siteInfo)) { if (LoginNameInfo.STATUS_TEMP.equals(nameInfo.getStatus())) { SessionUtils.setSessionVar(request, "otherUmt", otherUmt); String showUrl = RequestUtil.getContextPath(request) + "/show.do"; showUrl = RequestUtil.addParam(showUrl, "act", "showFilterActive"); if (isThirdBind) { showUrl = RequestUtil.addParam(showUrl, "type", authBy); } else { showUrl = RequestUtil.addParam(showUrl, "type", user.getType()); } showUrl = RequestUtil.addParam(showUrl, "oper", "login"); showUrl = RequestUtil.addParam(showUrl, "sendEmail", user.getCstnetId()); response.sendRedirect(showUrl); return; } } RoleService rs = (RoleService) factory.getBean(RoleService.BEAN_ID); UMTRole[] roles = rs.getUserRoles(username); UMTContext.saveRoles(session, roles); // 记住密码 String remember = request.getParameter("remember"); if ((remember != null) && (remember.equals("on") || remember.equals("yes"))) { generateSsoCookie(response, request, info); } generateAutoFill(response, request, info); // 加密用户凭证 if (siteInfo != null && !siteInfo.isEmpty()&&!isThirdBind) { SessionUtils.setSessionVar(request, Attributes.SITE_INFO, null); sendTicket(prins, siteInfo, request, response); } else { String returnUrl=request.getParameter("returnUrl"); if(siteInfo!=null&&StringUtils.isBlank(returnUrl)){ returnUrl=siteInfo.get(Attributes.RETURN_URL); } //如果是弱密码,且使用coreMail密码登录,请跳转到修改密码 if(info.isWeak()&&LoginInfo.TYPE_CORE_MAIL.equals(info.getPasswordType())){ String redirectUrl=RequestUtil.getContextPath(request)+"/user/manage.do?act=showChangePassword&weakPassword=true"; if(!CommonUtils.isNull(returnUrl)){ redirectUrl+="&returnUrl="+URLEncoder.encode(returnUrl, "UTF-8"); } response.sendRedirect(redirectUrl); }else{ if(!CommonUtils.isNull(returnUrl)){ response.sendRedirect(returnUrl); }else{ response.sendRedirect(RequestUtil.getContextPath(request) + "/index.jsp"); } } } } private void saveThirdPartyCredential(HttpServletRequest request, String authBy, String username, String password) { if (authBy != null &&!containEquals(new String[]{User.USER_TYPE_UMT,User.USER_TYPE_CORE_MAIL,User.USER_TYPE_MAIL_AND_UMT,BindInfo.TYPE_QQ,BindInfo.TYPE_CASHQ_SSO,BindInfo.TYPE_SINA,BindInfo.TYPE_UAF},authBy)) { ThirdPartyCredential tpc = new ThirdPartyCredential(username, password, authBy); request.getSession().setAttribute(Attributes.THIRDPARTY_CREDENTIAL, tpc); } } private boolean containEquals(String[] values,String value){ for(String str:values){ if(value.equals(str)){ return true; } } return false; } /** * 产生自动保持登陆的cookie * */ public static void generateSsoCookie(HttpServletResponse response, HttpServletRequest request, LoginInfo loginInfo) throws UnsupportedEncodingException { PCookie pcookie = (PCookie) ServiceFactory.getBean(request, "PCookie"); // 产生Pcookie String encrypted = pcookie.encrypt(loginInfo.getUser().getCstnetId() + "/" + RequestUtil.getRemoteIP(request) + "/" + loginInfo.getPasswordType() + "/" + System.currentTimeMillis()); Cookie cookie = new Cookie(Attributes.COOKIE_NAME, encrypted); cookie.setPath("/"); cookie.setMaxAge(MAX_COOKIE_AGE); response.addCookie(cookie); Cookie umtIdCookie = new Cookie(Attributes.SSO_FLAG, SessionUtils.getUserId(request) + ""); umtIdCookie.setDomain(Attributes.SSO_FLAG_DOMAIN); umtIdCookie.setPath("/"); umtIdCookie.setMaxAge(LoginMethod.MAX_COOKIE_AGE); response.addCookie(umtIdCookie); } public static void generateAutoFill(HttpServletResponse response, HttpServletRequest request, LoginInfo loginInfo) { Cookie autoFill = new Cookie(Attributes.AUTO_FILL, loginInfo.getLoginNameInfo().getLoginName()); autoFill.setPath("/"); autoFill.setMaxAge(Integer.MAX_VALUE); response.addCookie(autoFill); } /** * 返回cookie里的cookie信息 */ public static String getSsoCookieValue(HttpServletRequest request) { PCookie pcookie = (PCookie) ServiceFactory.getBean(request, "PCookie"); Cookie cookie = getCookieByName(request, Attributes.COOKIE_NAME); if (cookie == null) { return null; } return pcookie.decrypt(cookie.getValue()); } public static Cookie getCookieByName(HttpServletRequest request, String cookieName) { Cookie fcookie = null; if (cookieName != null) { Cookie[] cookies = request.getCookies(); if (cookies != null) { for (Cookie cookie : cookies) { if (cookieName.equals(cookie.getName())) { fcookie = cookie; break; } } } } return fcookie; } private boolean loginByCookie(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException, ApplicationNotFound { Cookie cookie = getCookieByName(request, Attributes.COOKIE_NAME); if (cookie == null) { return false; } if (StringUtils.isNotEmpty(cookie.getValue())) { String cookieValue = getSsoCookieValue(request); if (cookieValue != null) { LoginInfo info = ServiceFactory.getLoginService(request).loginAndReturnPasswordType( new CookieCredential(cookieValue, RequestUtil.getRemoteIP(request))); User userPrincipal = (info != null) ? info.getUser() : null; if (userPrincipal != null) { saveThirdPartyCredential(request, userPrincipal.getType(), cookieValue, ""); HttpSession session = request.getSession(); session.setAttribute(Attributes.LOGIN_INFO, info); // Roles RoleService rs = (RoleService) factory.getBean("RoleService"); UMTRole[] roles = rs.getUserRoles(cookieValue); UMTContext.saveRoles(session, roles); generateSsoCookie(response, request, info); generateAutoFill(response, request, info); String appname = request.getParameter(Attributes.APP_NAME); if (appname == null) { appname = (String) request.getAttribute(Attributes.APP_NAME); } if (appname != null) { sendTicket(userPrincipal, SessionUtils.getSiteInfo(request), request, response); } else { response.sendRedirect(RequestUtil.getContextPath(request) + "/index.jsp"); } return true; } request.setAttribute("cookieError", "true"); } } return false; } private boolean loginBySession(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException, ApplicationNotFound { HttpSession session = request.getSession(); LoginInfo loginInfo = UMTContext.getLoginInfo(session); User up = loginInfo.getUser(); if (up != null) { String appname = request.getParameter(Attributes.APP_NAME); if (appname == null) { appname = (String) request.getAttribute(Attributes.APP_NAME); } if (appname != null) { sendTicket(up, SessionUtils.getSiteInfo(request), request, response); } else { response.sendRedirect(RequestUtil.getContextPath(request) + "/index.jsp"); } return true; } return false; } private UserPrincipalV7 user2UserPrincipalV7(User user) { if (user == null) { return null; } UserPrincipalV7 en = new UserPrincipalV7(); en.setAuthBy(user.getType()); en.setPrimaryEmail(user.getCstnetId()); en.setSecondaryEmails(user.getSecondaryEmails()); en.setSecurityEmail(user.getSecurityEmail()); en.setTrueName(user.getTrueName()); en.setUmtId(user.getUmtId()); return en; } private void sendTicket(User up, Map<String, String> siteInfo, HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { boolean isVersion7 = "7".equals(request.getParameter(Attributes.UMT_VERSION)); UMTCredential cred = (UMTCredential) factory.getBean("UMTCredUtil"); SignedEnvelope env = null; if (isVersion7) { UserCredentialEnvelopeV7 userCredential = new UserCredentialEnvelopeV7(); userCredential.setAuthAppId(cred.getUMTId()); userCredential.setUser(user2UserPrincipalV7(up)); Date tommrow = DateUtils.addDays(new Date(), 1); userCredential.setValidTime(DateFormatUtils.format(tommrow, "yyyy-MM-dd hh:mm:ss")); env = new SignedEnvelope(userCredential.toXML(), cred.getUMTId()); } else { UserCredentialEnvelope userCredential = new UserCredentialEnvelope(); userCredential.setAuthAppId(cred.getUMTId()); userCredential.setUser(up == null ? null : up.getUserPrincipal()); Date tommrow = DateUtils.addDays(new Date(), 1); userCredential.setValidTime(DateFormatUtils.format(tommrow, "yyyy-MM-dd hh:mm:ss")); env = new SignedEnvelope(userCredential.toXML(), cred.getUMTId()); } env.genSignature(cred.getUMTKey()); request.setAttribute("signedCredential", Base64Util.encodeBase64(env.toXML())); SessionService seService = (SessionService) factory.getBean("SessionService"); String loginByDeputyResult = siteInfo.get(Attributes.APP_DEPUTY_LOGIN_RESULT_KEY); if (loginByDeputyResult != null) { request.setAttribute(Attributes.APP_DEPUTY_LOGIN_RESULT_KEY, loginByDeputyResult); } if (loginByDeputyResult == null || "success".equals(loginByDeputyResult)) { seService.login(siteInfo.get(Attributes.APP_NAME), up.getCstnetId(), RequestUtil.getRemoteIP(request), siteInfo.get(Attributes.LOGOUT_URL), "JSP", siteInfo.get(Attributes.SESSION_ID_KEY)); } request.setAttribute(Attributes.RETURN_URL, siteInfo.get(Attributes.RETURN_URL)); ServiceFactory.getAppAccessService(request).createAppAccess(up == null ? -1 : up.getId(), siteInfo.get(Attributes.APP_NAME)); doForward("/post.jsp", request, response); } protected void doForward(String url, HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { String mappedURL = getThemedJSP(request, url); RequestDispatcher rd = request.getSession().getServletContext().getRequestDispatcher(mappedURL); rd.forward(request, response); } protected BeanFactory factory; // 24 hours*14 public static final int MAX_COOKIE_AGE = 10 * 60 * 60 * 24; }