使用者登入範例分析,使用者登入範例
多重網路節點
項目使用的是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 * 參數: request10 * loginAccount11 * password12 * 傳回值類型: ProcResult13 *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 userId25 * @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 userId32 * @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();// 儲存已登入帳號的類 單例模式(已經解決線程建立問題): 主要是裡面的map14 // 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);// 給使用者佈建許可權等級為415 } else if("mkadmin".equals(user.getLoginName()) || Sys.FACILITATOR_ADMIN == (int) user.getType()) { //如果他是admin16 user.setAuthLevel(1);// 給使用者佈建許可權為 1 17 } else { // 若有18 int dftOrgIndex = -1;19 Org psOrg = null;20 for(int i=0; i<orgs.size(); i++){ //遍曆list ->orgs21 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); //許可權等級為239 } else { 40 user.setAuthLevel(Sys.DPT_ADMIN);//341 }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