首页 > 代码库 > Java SSH框架系列:用户登录模块的设计与实现思路

Java SSH框架系列:用户登录模块的设计与实现思路

 

时间 2014-01-19 16:14:54  CSDN博客原文  http://blog.csdn.net/nupt123456789/article/details/18504615
1.简介 
用户登录模块,指的是根据用户输入的用户名和密码,对用户的身份进行验证等。如果用户没有登录,用户就无法访问其他的一些jsp页面,甚至是action都不能访问。 
二、简单设计及实现 
本程序是基于Java的SSH框架进行的。 
1.数据库设计 

我们应该设计一个用户表,其Userinfo表,对应的SQL语句为(Oracle数据库):

create table userinfo(  id                        varchar2(36) primary key,  username                 varchar2(50) not null,  password                 varchar2(50) not null,  auth_limit               varchar2(10) not null,  register_time           varchar2(40),  create_time             varchar2(40),  remarks                  varchar2(1024)               );
分别是id,也就是UUID,用户名、密码、权限、注册时间、记录插入数据库的时间、备注等几个字段。

2.使用MyEclipse的Hibernate逆向工具,生成对应的Java Bean和相应的hibernate的xml配置文件Userinfo.hbm.xml 

package edu.njupt.zhb.bean;/** * Userinfo entity. @author MyEclipse Persistence Tools */public class Userinfo implements java.io.Serializable {  // Fields  private String id;  private String username;  private String password;  private String authLimit;  private String registerTime;  private String createTime;  private String remarks;  // Constructors  /** default constructor */  public Userinfo() {  }  /** minimal constructor */  public Userinfo(String id, String username, String password,      String authLimit) {    this.id = id;    this.username = username;    this.password = password;    this.authLimit = authLimit;  }  /** full constructor */  public Userinfo(String id, String username, String password,      String authLimit, String registerTime, String createTime,      String remarks) {    this.id = id;    this.username = username;    this.password = password;    this.authLimit = authLimit;    this.registerTime = registerTime;    this.createTime = createTime;    this.remarks = remarks;  }  // Property accessors  public String getId() {    return this.id;  }  public void setId(String id) {    this.id = id;  }  public String getUsername() {    return this.username;  }  public void setUsername(String username) {    this.username = username;  }  public String getPassword() {    return this.password;  }  public void setPassword(String password) {    this.password = password;  }  public String getAuthLimit() {    return this.authLimit;  }  public void setAuthLimit(String authLimit) {    this.authLimit = authLimit;  }  public String getRegisterTime() {    return this.registerTime;  }  public void setRegisterTime(String registerTime) {    this.registerTime = registerTime;  }  public String getCreateTime() {    return this.createTime;  }  public void setCreateTime(String createTime) {    this.createTime = createTime;  }  public String getRemarks() {    return this.remarks;  }  public void setRemarks(String remarks) {    this.remarks = remarks;  }}
3.新建一个UserInfoService接口
/* * $filename: VideoInfoService.java,v $ * $Date: 2014-1-2  $ * Copyright (C) ZhengHaibo, Inc. All rights reserved. * This software is Made by Zhenghaibo. */package edu.njupt.zhb.service;import edu.njupt.zhb.bean.Userinfo;/* *@author: ZhengHaibo   *web:     http://blog.csdn.net/nuptboyzhb *GitHub   https://github.com/nuptboyzhb *mail:    zhb931706659@126.com *2014-1-2  Nanjing,njupt,China */public interface UserInfoService {  String getUserInfoList(int page, int rows);  String addUser(Userinfo userinfo);  String deleteUser(String userId);  String editUser(Userinfo userinfo);  Userinfo getUserInfoByName(String username);}
4.新建一个UserInfoServiceImpl类
/* * $filename: VideoInfoServiceImpl.java,v $ * $Date: 2014-1-2  $ * Copyright (C) ZhengHaibo, Inc. All rights reserved. * This software is Made by Zhenghaibo. */package edu.njupt.zhb.service.impl;import java.util.ArrayList;import java.util.List;import net.sf.json.JSONObject;import edu.njupt.zhb.bean.Userinfo;import edu.njupt.zhb.dao.BaseDao;import edu.njupt.zhb.service.UserInfoService;import edu.njupt.zhb.utils.DataGrid;import edu.njupt.zhb.utils.Tips;import edu.njupt.zhb.view.ViewUser;/* *@author: ZhengHaibo   *web:     http://blog.csdn.net/nuptboyzhb *GitHub   https://github.com/nuptboyzhb *mail:    zhb931706659@126.com *2014-1-2  Nanjing,njupt,China */public class UserInfoServiceImpl implements UserInfoService{  private BaseDao<Userinfo> userinfoBaseDao;  public BaseDao<Userinfo> getUserBaseDao() {    return userinfoBaseDao;  }  public void setUserBaseDao(BaseDao<Userinfo> userinfoBaseDao) {    this.userinfoBaseDao = userinfoBaseDao;  }  @Override  public String getUserInfoList(int page, int rows) {    // TODO Auto-generated method stub    System.out.println("page="+page+",rows="+rows);    String hql = "from Userinfo";    try {      List<Userinfo> list = userinfoBaseDao.find(hql,page,rows);      List<ViewUser> resultList = new ArrayList<ViewUser>();      for(Userinfo userinfo:list){        ViewUser viewUser = new ViewUser();        viewUser.setBz(userinfo.getRemarks());        viewUser.setId(userinfo.getId());        viewUser.setPwd(userinfo.getPassword());        viewUser.setYhm(userinfo.getUsername());        viewUser.setYhqx(userinfo.getAuthLimit());        viewUser.setZcsj(userinfo.getRegisterTime());        resultList.add(viewUser);      }      DataGrid<ViewUser> dataGrid = new DataGrid<ViewUser>();      dataGrid.setRows(resultList);      dataGrid.setTotal(userinfoBaseDao.total(hql));      String result = JSONObject.fromObject(dataGrid).toString();      return result;    } catch (Exception e) {      e.printStackTrace();      return null;    }  }    public String addUser(Userinfo userinfo) {    // TODO Auto-generated method stub    Tips tips = new Tips();    String hql = "from Userinfo where username = ‘"+userinfo.getUsername()+"‘";    try {      List<Userinfo> list =  userinfoBaseDao.find(hql);      if(list!=null&&list.size()>0){        tips.setMsg("添加失败!用户名已经存在!");        return JSONObject.fromObject(tips).toString();      }    } catch (Exception e) {      // TODO Auto-generated catch block      e.printStackTrace();    }    try {      userinfoBaseDao.save(userinfo);    } catch (Exception e) {      // TODO Auto-generated catch block      e.printStackTrace();      tips.setMsg("添加失败");      return JSONObject.fromObject(tips).toString();    }    tips.setMsg("添加成功");    return JSONObject.fromObject(tips).toString();  }  public String deleteUser(String userid) {    // TODO Auto-generated method stub    Tips tips = new Tips();    try {      userinfoBaseDao.executeHql("delete from Userinfo where id = ‘"+userid+"‘");    } catch (Exception e) {      // TODO Auto-generated catch block      e.printStackTrace();      tips.setMsg("删除失败");      return JSONObject.fromObject(tips).toString();    }    tips.setMsg("删除成功");    return JSONObject.fromObject(tips).toString();  }  public String editUser(Userinfo userinfo) {    // TODO Auto-generated method stub    Tips tips = new Tips();    String hql = "from Userinfo where username = ‘"+userinfo.getUsername()+"‘";    try {      List<Userinfo> list =  userinfoBaseDao.find(hql);      if(list!=null&&list.size()>0){        tips.setMsg("更新失败!用户名已经存在!");        return JSONObject.fromObject(tips).toString();      }    } catch (Exception e) {      // TODO Auto-generated catch block      e.printStackTrace();    }    try {      userinfoBaseDao.update(userinfo);    } catch (Exception e) {      // TODO Auto-generated catch block      e.printStackTrace();      tips.setMsg("编辑失败");      return JSONObject.fromObject(tips).toString();    }    tips.setMsg("编辑成功");    return JSONObject.fromObject(tips).toString();  }  @Override  public Userinfo getUserInfoByName(String username) {    // TODO Auto-generated method stub    Userinfo  userinfo = null;    String hql = "from Userinfo where username = ‘"+username+"‘";    try {      List<Userinfo> list =  userinfoBaseDao.find(hql);      if(list == null || list.size()==0){        return null;      }      userinfo = list.get(0);      return userinfo;    } catch (Exception e) {      // TODO Auto-generated catch block      e.printStackTrace();    }    return null;  }}
5.新建UserInfoAction类,(当然,我们的BaseAction肯定是从struts2中的ActionSupport派生出来的)
/* * $filename: VideoInfoAction.java,v $ * $Date: 2014-1-2  $ * Copyright (C) ZhengHaibo, Inc. All rights reserved. * This software is Made by Zhenghaibo. */package edu.njupt.zhb.action;import java.util.UUID;import net.sf.json.JSONArray;import net.sf.json.JSONObject;import edu.njupt.zhb.bean.Userinfo;import edu.njupt.zhb.service.UserInfoService;import edu.njupt.zhb.utils.Tips;import edu.njupt.zhb.utils.TipsMsg;import edu.njupt.zhb.utils.Utils;/* *@author: ZhengHaibo   *web:     http://blog.csdn.net/nuptboyzhb *GitHub   https://github.com/nuptboyzhb *mail:    zhb931706659@126.com *2014-1-2  Nanjing,njupt,China */public class UserInfoAction extends BaseAction {  /**   *    */  private static final long serialVersionUID = 3321845277376234101L;  private Userinfo userinfo;  private String userId;  private String username;  private String password;  public String getPassword() {    return password;  }  public void setPassword(String password) {    this.password = password;  }  public String getUsername() {    return username;  }  public void setUsername(String username) {    this.username = username;  }  public String getUserId() {    return userId;  }  public void setUserId(String userId) {    this.userId = userId;  }  public Userinfo getUserinfo() {    return userinfo;  }  public void setUserinfo(Userinfo userinfo) {    this.userinfo = userinfo;  }  private UserInfoService userInfoService;  public UserInfoService getUserInfoService() {    return userInfoService;  }  public void setUserInfoService(UserInfoService userInfoService) {    this.userInfoService = userInfoService;  }  public void getUserInfoList() {    String jsonResult = userInfoService.getUserInfoList(page, rows);    System.out.println(jsonResult);    super.writeStr(jsonResult);  }  /**   * 添加用户   *    * @return   */  public void addUser() {    if (userinfo == null) {      Tips tips = new Tips();      tips.setMsg("添加失败!对象为空");      getPrintWriter().write(JSONArray.fromObject(tips).toString());      return;    }    userinfo.setId(UUID.randomUUID() + "");    userinfo.setCreateTime(Utils.getNowTime());    String jsonResult = userInfoService.addUser(userinfo);    getPrintWriter().write(jsonResult);  }  /**   * 删除用户   *    * @return   */  public void deleteUser() {    if (userId == null) {      Tips tips = new Tips();      tips.setMsg("删除失败!学号无效");      getPrintWriter().write(JSONArray.fromObject(tips).toString());      return;    }    String jsonResult = userInfoService.deleteUser(userId);    getPrintWriter().write(jsonResult);  }  /**   * 编辑用户   *    * @return   */  public void editUser() {    if (userinfo == null) {      Tips tips = new Tips();      tips.setMsg("编辑失败!对象为空");      getPrintWriter().write(JSONArray.fromObject(tips).toString());      return;    }    userinfo.setId(userId);    String jsonResult = userInfoService.editUser(userinfo);    getPrintWriter().write(jsonResult);  }  public void login() {    TipsMsg tipsMsg = new TipsMsg();    if(username==null){      tipsMsg.setId("1");      tipsMsg.setMsg("用户名为空!");      String result = JSONObject.fromObject(tipsMsg).toString();      super.writeStr(result);      return;    }    Userinfo userinfo = userInfoService.getUserInfoByName(username);    if(userinfo==null){      tipsMsg.setId("1");      tipsMsg.setMsg("用户名不存在");      String result = JSONObject.fromObject(tipsMsg).toString();      super.writeStr(result);      return;    }    if(!userinfo.getPassword().equals(password)){      tipsMsg.setId("1");      tipsMsg.setMsg("用户名或密码错误");      String result = JSONObject.fromObject(tipsMsg).toString();      super.writeStr(result);      return;    }    super.setCurrentUser(userinfo);    tipsMsg.setId("2");    tipsMsg.setMsg("登录成功");    String result = JSONObject.fromObject(tipsMsg).toString();    super.writeStr(result);    return;  }}
6.配置Spring的applicationContext.xml文件,依次注入Dao、Service和Action。
<bean id="baseDao" class="edu.njupt.zhb.dao.BaseDao">    	<property name="sessionFactory" ref="sessionFactory"></property>    </bean>
<bean id="userInfoService" class="edu.njupt.zhb.service.impl.UserInfoServiceImpl">    	<property name="userBaseDao" ref="baseDao"></property>    </bean>
<bean id="userInfoAction" class="edu.njupt.zhb.action.UserInfoAction" scope="prototype">    <property name="userInfoService" ref="userInfoService"></property>  </bean>
7.配置Spring的Hibernate的Java Bean的映射文件
<bean id="sessionFactory"    class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">    <property name="dataSource" ref="dataSource" />    <property name="hibernateProperties">      <props>          <prop key="hibernate.show_sql">true</prop>        <prop key="hibernate.dialect">org.hibernate.dialect.OracleDialect</prop>        <prop key="current_session_context_class">thread</prop>      </props>    </property>    <property name="mappingResources">      <list>          ...        <value>edu/njupt/zhb/bean/Userinfo.hbm.xml</value>      </list>    </property>  </bean>
8.配置Struts2文件,增加相应的Action,login等 
<action name="getUserInfoList" class="userInfoAction" method="getUserInfoList"></action>    <action name="addUser" class="userInfoAction" method="addUser"></action>    <action name="deleteUser" class="userInfoAction" method="deleteUser"></action>    <action name="editUser" class="userInfoAction" method="editUser"></action>    <action name="login" class="userInfoAction" method="login"></action>
9.登录页面login.jsp中的ajax请求: 
$("#btnLogin").click(function(){      var message = "";      var userName=$(‘input[name="userName"]‘).val();      var userPass=$(‘input[name="userPass"]‘).val();      if(userName == ""){        alert("请输入用户名!");        return;      }else if(userPass == ""){        alert("请输入密码!");        return;      }      $.ajax({                type:"post",                url:‘login.action?username=‘+userName+‘&password=‘+userPass,                dateType:"json",                success:function(data){            var json=eval("("+data+")");                    if(json.id==‘1‘){                	   alert(json.msg);                	   return;                    }else{                	   $("#frm").submit();                    }          }            });        });
10.为了防止用户在不登陆的情况下,访问其他页面,我们在每一个jsp页面中添加如下代码: 
<%if(null == request.getSession().getAttribute("user")){       response.getWriter().write("<script>window.location.href = http://www.mamicode.com/‘login.jsp‘</script>");     }     %>
思考 : 
完成上述复杂的功能之后,我们是不是就完成任务了呢?显然不是,我们经过测试我们就会发现,在我们没有登录的情况下,我们确实没有办法访问其他的JSP页面,但是我们可以直接在浏览器中访问struts中配置的action!这依然有很大的漏洞,那我们怎么对action进行拦截呢?也即是对非login.action进行拦截判断,如果用户已经登录,就正常登录,如果用户没有登录,就返回login,让其登录。因此我们需要使用struts2的拦截器。

11.拦截器的Java代码 

/* * $filename: CheckLoginInterceptor.java,v $ * $Date: 2014-1-15  $ * Copyright (C) ZhengHaibo, Inc. All rights reserved. * This software is Made by Zhenghaibo. */package edu.njupt.zhb.utils;import java.util.Map;import com.opensymphony.xwork2.ActionInvocation;import com.opensymphony.xwork2.interceptor.AbstractInterceptor;import edu.njupt.zhb.action.UserInfoAction;import edu.njupt.zhb.bean.Userinfo;/* *@author: ZhengHaibo   *web:     http://blog.csdn.net/nuptboyzhb *GitHub   https://github.com/nuptboyzhb *mail:    zhb931706659@126.com *2014-1-15  Nanjing,njupt,China */public class CheckLoginInterceptor extends AbstractInterceptor{  /**   *    */  private static final long serialVersionUID = 2092930262572782343L;  @Override  public String intercept(ActionInvocation actionInvocation) throws Exception {    // TODO Auto-generated method stub    //System.out.println("begin check login interceptor!");        // 对LoginAction不做该项拦截        Object action = actionInvocation.getAction();        if (action instanceof UserInfoAction) {            //System.out.println("exit check login, because this is login action.");            //UserInfoAction userinfoAction = (UserInfoAction)action;            return actionInvocation.invoke();        }        // 确认Session中是否存在User        Map<String,Object> session = actionInvocation.getInvocationContext().getSession();        Userinfo user = (Userinfo) session.get("user");        if (user != null) {            // 存在的情况下进行后续操作。            //System.out.println("already login!");            return actionInvocation.invoke();        } else {            // 否则终止后续操作,返回LOGIN            System.out.println("no login, forward login page!");            return "login";        }  }}
12.拦截器在Struts2中的配置 
<interceptor name="loginIntercepter"        class="edu.njupt.zhb.utils.CheckLoginInterceptor">      </interceptor>      <!-- 拦截器栈 -->      <interceptor-stack name="loginStack">        <interceptor-ref name="defaultStack" />        <interceptor-ref name="loginIntercepter" />      </interceptor-stack>
为每一个action配置拦截器,比如:
<action name="getStudentList" class="dataGridDemoAction"      method="getStudentList">      <result type="httpheader"></result>      <interceptor-ref name="loginStack" />      <result name="login">/login.jsp</result>    </action>    <action name="addStudent" class="dataGridDemoAction" method="addStudent">      <result type="httpheader"></result>      <interceptor-ref name="loginStack" />      <result name="login">/login.jsp</result>    </action>    <action name="deleteStudent" class="dataGridDemoAction" method="deleteStudent">      <result type="httpheader"></result>      <interceptor-ref name="loginStack" />      <result name="login">/login.jsp</result>    </action>    <action name="editStudent" class="dataGridDemoAction" method="editStudent">      <result type="httpheader"></result>      <interceptor-ref name="loginStack" />      <result name="login">/login.jsp</result>    </action>
当然,对于用户登录的action,我们也配置相应的拦截器:
<!-- 用户信息Action -->    <action name="getUserInfoList" class="userInfoAction" method="getUserInfoList">      <interceptor-ref name="loginStack" />      <result name="login">/login.jsp</result>    </action>    <action name="addUser" class="userInfoAction" method="addUser">      <interceptor-ref name="loginStack" />      <result name="login">/login.jsp</result>    </action>    <action name="deleteUser" class="userInfoAction" method="deleteUser">      <interceptor-ref name="loginStack" />      <result name="login">/login.jsp</result>    </action>    <action name="editUser" class="userInfoAction" method="editUser">      <interceptor-ref name="loginStack" />      <result name="login">/login.jsp</result>    </action>    <action name="login" class="userInfoAction" method="login">      <interceptor-ref name="loginStack" />    </action>
总结:

以上步骤完成之后,我们基本上就完成了一个简单的用户登录模块的设计和实现了。而且我们可以根据用户的权限,显示不同的内容。比如管理员和普通操作员等具有不同的操作权限。 

说明:

以上代码只是一些代码片段,我这里主要介绍的是思路。以上代码还有一些小小的漏洞,比如,我们在没有登录的情况下,还是可以直接访问getUserinfoList、deleteUser、editUser等与login在同一个Action类中的action。因此,我们设计的时候,要尽量将login和logout单独一个action。还有:上面写的getUserinfoList等一些action,目的是管理员对用户表进行增删改查等操作的,和本博客关系不大。本文主要注意的是:一个是在jsp页面中对未登陆用户的拦截,还有就是通过配置Struts2的拦截器,对未登录用户直接访问action方式进行拦截的。

未经允许,不得用于商业目的

Java SSH框架系列:用户登录模块的设计与实现思路