多點登錄
項目使用的是SSM(Spring SpringMVC Mybatis);
到登錄頁面的流程:
項目啟動歡迎界面: index.jsp
直接跳轉:<%response.sendRedirect("/login/forwardLogin") %>
>>請求到Controller的 forwardLogin()方法中:
1 @RequestMapping("/forwardLogin") 2 public ModelAndView forwardLogin(HttpServletRequest request) { 3 ModelAndView mav = new ModelAndView("login");//mav模型視圖解析器 定義返回地址 4 String msg = request.getParameter("res_msg")==null?"":request.getParameter("res_msg"); // 為錯誤信息准備的 鍵值對獲取 並設定到mav對象中 5 mav.addObject("res_msg", msg); 6 return mav; 7 }
>>springmvc解析到 login.jsp中
信息展示標簽: <p class="login-error">${res_msg}</p>
login.jsp是登錄界面 輸入賬號密碼 提交時 密碼用MD5加密!
<form action="<%=contextPath%>/login/userLogin" id="loginForm" method="post">
請求到 userLogin()方法中:
1 @RequestMapping("/userLogin") 2 public ModelAndView userLogin(HttpServletRequest request) { 3 ModelAndView mav = null; 4 String loginAccount = request.getParameter("loginAccount"); 5 //獲取賬號密碼 6 String password = request.getParameter("password"); 7 /** 8 * 業務邏輯層方法調用: 9 * 參數: request 10 * loginAccount 11 * password 12 * 返回值類型: ProcResult 13 * 14 * 下面有ProcResult的代碼和 userService.userLogin()的方法分析(多點登錄的實現)! 15 **/ 16 ProcResult result = userService.userLogin(request, loginAccount, password); 17 18 if(Sys.LOGIN_SUCCESS == result.getResCode()){// 若登錄成功了 19 User user = (User) request.getSession().getAttribute("USER");//從session獲取USER存儲的對象 20 switch (user.getAuthLevel()) {//獲取用戶等級(權限控制) 21 case 1: 22 mav = new ModelAndView("redirect:/user/forwardHomePage"); 23 break; 24 // mav = new ModelAndView("redirect:/org/showOrgInfo"); 25 // case 2: 26 // break; 27 // case 3: 28 // break; 29 // case 4: 30 // break; 31 default: 32 mav = new ModelAndView("redirect:/user/forwardHomePage"); 33 // mav = new ModelAndView("redirect:/org/showOrgDeptInfo"); 34 } 35 } else {// 沒成功 重定向:!!! 重定向是指請求的重定向 36 mav = new ModelAndView("redirect:/login/forwardLogin");// 又定向到了index.jsp跳轉到的方法 37 mav.addObject("res_msg", result.getResMsg());//添加上相關的錯誤信息 38 } 39 return mav; 40 }
///////////////////////////////////////////////////////////////////
1 ProcResult 類代碼: 2 public class ProcResult implements Serializable { 3 // result的代碼 4 private int resCode; 5 // result的信息 6 private String resMsg; 7 //主要用到了前兩個屬性 8 private Map<String, String> info; 9 private Map<String, Object> extra; 10 public static ProcResult buildResult(int code, String msg){ 11 ProcResult result = new ProcResult(code, msg); 12 return result; 13 } 14 public ProcResult(){}//無參構造! 15 public ProcResult(int code, String msg) { //兩個參數的構造方法 16 this.resCode = code; 17 this.resMsg = msg; 18 //只看前兩個屬性就可以了! 19 this.info = new HashMap<String, String>(); 20 this.extra = new HashMap<String, Object>(); 21 } 22 //getter&setter 不再贅述 23 }
1 LoginAccount類代碼: 2 /** 3 * 保存用戶登錄信息 4 */ 5 public class LoginAccount { 6 private static Map<String, Map<String, Object>> accountInfo = null; 7 private LoginAccount() {} 8 private static LoginAccount instance = null; 9 public static LoginAccount getInstance() {//對外提供靜態的公共的方法 10 if (instance == null) { //首次創建的情況下 11 synchronized (LoginAccount.class) { // 對類進行加鎖 12 LoginAccount temp = instance; 13 if (temp == null) { // 雙城判斷解決 多線程會創建多個對象的問題 14 temp = new LoginAccount(); 15 instance = temp; 16 accountInfo = new HashMap<String, Map<String, Object>>();//首次創建的時候聲明一個Map對象 用於存放相關的賬戶信息 17 } 18 } 19 } 20 return instance; 21 } 22 23 /** * 保存用戶登錄信息 24 * @param userId 25 * @param accountInfo */ 26 public void addLogin(String userId, Map<String, Object> accountInfo) { 27 this.accountInfo.put(userId, accountInfo); //將賬戶以鍵值對的形式存放到當前的map(map也就是唯一的)中 28 // the key is userId , and value is accountInfo(賬戶信息) 29 } 30 /** * 校驗用戶是否已登錄 31 * @param userId 32 * @return boolean */ 33 public boolean checkLogin(String userId) { 34 boolean flag = false; 35 if (this.accountInfo.containsKey(userId)) { //判斷是否包含此鍵 36 flag = true; 37 } 38 return flag; 39 } 40 /*** 移除用戶登錄信息 41 * @param userId */ 42 public void removeLogin(String userId) { 43 this.accountInfo.remove(userId); //從map中刪除 44 } 45 }
1 /////////////////////////////service層的方法////////////////////////////////////// 2 public ProcResult userLogin(HttpServletRequest request,String loginAccount, String password) { 3 User user = null; 4 user = userDao.getLoginUserInfo(loginAccount);//根據賬戶查出用戶的相關信息: 5 /**sql: SELECT m.*, o.duration 6 FROM m_user m LEFT JOIN m_org o ON m.src_org=o.org_id 7 WHERE 1=1 8 AND m.del=0 //沒有刪除的標記 9 AND (m.login_name=#{loginAccount} //賬戶名登錄 10 OR m.mobile=#{loginAccount} //手機號登錄 11 OR m.email=#{loginAccount}) //郵箱登錄 12 */ 13 LoginAccount la = LoginAccount.getInstance();// 保存已登錄賬號的類 單例模式(已經解決線程創建問題): 主要是裡面的map 14 // 15 if(null!=user){//查出了用戶的相關信息 16 String userPassword = user.getPassword().trim(); 17 if(userPassword.equals(password)){ //如果密碼匹配成功 18 boolean loginFlag = la.checkLogin(""+user.getUserId());// 檢查此賬戶是否登錄 19 int multiLogin = user.getMultiLogin(); // 獲取用戶是否允許多點登錄標示 20 List<Org> orgs = orgDao.getUserOrgs(user.getUserId()); //獲取用戶所屬組織的相關信息 21 if(loginFlag){//已經登錄 22 if(1 == multiLogin || 999==multiLogin){//允許多點登陸 23 result = new ProcResult(Sys.LOGIN_SUCCESS, Message.LOGIN_SUCCESS); // 登錄成功標示及信息 24 initLoginUserInfo(user, orgs, request);// 方法解析在下面 25 } else {//不允許多點登陸 26 result = new ProcResult(Sys.LOGIN_MULTI_LOGIN, Message.MULTI_LOGIN);// 不允許多點登錄 標示及信息 27 } 28 } else {//未登錄 29 Date today = new Date(); 30 Date duration = user.getDuration();// 用戶的服務期限 31 if(null==duration || duration.before(today)){ // 已經到期或者為空 32 result = new ProcResult(Sys.LOGIN_OUT_DURATION, Message.OUT_DURATION); //服務到期 標示及信息 33 } else {//成功 34 initLoginUserInfo(user, orgs, request); 35 result = new ProcResult(Sys.LOGIN_SUCCESS, Message.LOGIN_SUCCESS); // 登錄成功標示及信息 36 } 37 38 } 39 // initLoginUserInfo中的參數已經對user進行了操作 他們操作的是同一個user 同一個對象!! 40 result.getExtra().put("USER", user); // 將其放到 ProResult中去 41 } else { 42 result = new ProcResult(Sys.LOGIN_WRONG_PWD, Message.WRONG_PWD);// 密碼錯誤 標示及信息 43 } 44 45 } else { 46 result = new ProcResult(Sys.LOGIN_WRONG_USER, Message.NONE_USER); // 用戶不存在 標示及信息 47 } 48 return result; 49 }
1 // initLoginUserInfo(user, orgs, request) 方法解析 2 // 此方法是在BaseService中的方法: 3 /** 4 * 在session中保存用戶登錄信息 5 * @param user orgs request 6 * @return 7 */ 8 protected boolean initLoginUserInfo(User user, List<Org> orgs, HttpServletRequest request) { 9 boolean flag = false; 10 HttpSession session = request.getSession(); 11 Org o = null; 12 13 if(orgs.size()==0) {// 如果 用戶沒有任何組織 14 user.setAuthLevel(4);// 給用戶設置權限等級為4 15 } else if("mkadmin".equals(user.getLoginName()) || Sys.FACILITATOR_ADMIN == (int) user.getType()) { //如果他是admin 16 user.setAuthLevel(1);// 給用戶設置權限為 1 17 } else { // 若有 18 int dftOrgIndex = -1; 19 Org psOrg = null; 20 for(int i=0; i<orgs.size(); i++){ //遍歷list ->orgs 21 Org org = orgs.get(i); 22 int orgId = org.getOrgId(); 23 int userDftOrg = user.getDefaultOrgId(); 24 if(orgId == userDftOrg) { //如果默認值就是此組織? 25 dftOrgIndex = i; 26 } 27 //個人組織 28 if(0 == org.getType()){ //個人空間 29 psOrg = org; 30 } 31 } 32 if(-1 != dftOrgIndex){ 33 o = orgs.get(dftOrgIndex); 34 //如果登錄用是默認組織的組織管理員 35 int userId = user.getUserId(); 36 int orgAdminId = o.getAdminId(); 37 if(userId == orgAdminId){ //當前啊組織的管理員 38 user.setAuthLevel(2); //權限等級為2 39 } else { 40 user.setAuthLevel(Sys.DPT_ADMIN);//3 41 } 42 session.setAttribute(Sys.SESSION_ORG, o); //設置到session中 "ORG" 43 } else { 44 if(null!=psOrg){ 45 psOrg.setDefaultOrg(1); 46 session.setAttribute(Sys.SESSION_ORG, psOrg); 47 } 48 } 49 } 50 session.setAttribute("USER_ORGS", orgs);//用戶所有的組織信息 51 session.setAttribute(Sys.SESSION_USER, user); //用戶信息 52 Map<String, Object> accInfo = new HashMap<String, Object>();// 53 LoginAccount la = LoginAccount.getInstance(); 54 if(!la.checkLogin(""+user.getUserId())){//檢查是否當前用戶登錄了 55 //暫時注釋掉 56 // accInfo.put("USER", user); 57 // LoginAccount.getInstance().addLogin(""+user.getUserId(), accInfo); 58 } 59 flag = true; 60 return flag; 61 }
wunian7yulian 16.4.5