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

简介: 时间 2014-01-19 16:14:54  CSDN博客原文  http://blog.csdn.net/nupt123456789/article/details/18504615 1.简介 用户登录模块,指的是根据用户输入的用户名和密码,对用户的身份进行验证等。

 

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 = '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方式进行拦截的。

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

目录
相关文章
|
4月前
|
Java 数据库
在Java中使用Seata框架实现分布式事务的详细步骤
通过以上步骤,利用 Seata 框架可以实现较为简单的分布式事务处理。在实际应用中,还需要根据具体业务需求进行更详细的配置和处理。同时,要注意处理各种异常情况,以确保分布式事务的正确执行。
|
4月前
|
消息中间件 Java Kafka
在Java中实现分布式事务的常用框架和方法
总之,选择合适的分布式事务框架和方法需要综合考虑业务需求、性能、复杂度等因素。不同的框架和方法都有其特点和适用场景,需要根据具体情况进行评估和选择。同时,随着技术的不断发展,分布式事务的解决方案也在不断更新和完善,以更好地满足业务的需求。你还可以进一步深入研究和了解这些框架和方法,以便在实际应用中更好地实现分布式事务管理。
|
3月前
|
存储 安全 Java
Java 集合框架中的老炮与新秀:HashTable 和 HashMap 谁更胜一筹?
嗨,大家好,我是技术伙伴小米。今天通过讲故事的方式,详细介绍 Java 中 HashMap 和 HashTable 的区别。从版本、线程安全、null 值支持、性能及迭代器行为等方面对比,帮助你轻松应对面试中的经典问题。HashMap 更高效灵活,适合单线程或需手动处理线程安全的场景;HashTable 较古老,线程安全但性能不佳。现代项目推荐使用 ConcurrentHashMap。关注我的公众号“软件求生”,获取更多技术干货!
61 3
|
4月前
|
JSON Java Apache
非常实用的Http应用框架,杜绝Java Http 接口对接繁琐编程
UniHttp 是一个声明式的 HTTP 接口对接框架,帮助开发者快速对接第三方 HTTP 接口。通过 @HttpApi 注解定义接口,使用 @GetHttpInterface 和 @PostHttpInterface 等注解配置请求方法和参数。支持自定义代理逻辑、全局请求参数、错误处理和连接池配置,提高代码的内聚性和可读性。
298 3
|
27天前
|
存储 缓存 Java
java语言后台管理ruoyi后台管理框架-登录提示“无效的会话,或者会话已过期,请重新登录。”-扩展知识数据库中密码加密的方法-问题如何解决-以及如何重置若依后台管理框架admin密码-优雅草卓伊凡
java语言后台管理ruoyi后台管理框架-登录提示“无效的会话,或者会话已过期,请重新登录。”-扩展知识数据库中密码加密的方法-问题如何解决-以及如何重置若依后台管理框架admin密码-优雅草卓伊凡
93 3
java语言后台管理ruoyi后台管理框架-登录提示“无效的会话,或者会话已过期,请重新登录。”-扩展知识数据库中密码加密的方法-问题如何解决-以及如何重置若依后台管理框架admin密码-优雅草卓伊凡
|
5月前
|
存储 Java
深入探讨了Java集合框架中的HashSet和TreeSet,解析了两者在元素存储上的无序与有序特性。
【10月更文挑战第16天】本文深入探讨了Java集合框架中的HashSet和TreeSet,解析了两者在元素存储上的无序与有序特性。HashSet基于哈希表实现,添加元素时根据哈希值分布,遍历时顺序不可预测;而TreeSet利用红黑树结构,按自然顺序或自定义顺序存储元素,确保遍历时有序输出。文章还提供了示例代码,帮助读者更好地理解这两种集合类型的使用场景和内部机制。
68 3
|
4天前
|
存储 监控 数据可视化
SaaS云计算技术的智慧工地源码,基于Java+Spring Cloud框架开发
智慧工地源码基于微服务+Java+Spring Cloud +UniApp +MySql架构,利用传感器、监控摄像头、AI、大数据等技术,实现施工现场的实时监测、数据分析与智能决策。平台涵盖人员、车辆、视频监控、施工质量、设备、环境和能耗管理七大维度,提供可视化管理、智能化报警、移动智能办公及分布计算存储等功能,全面提升工地的安全性、效率和质量。
|
2月前
|
并行计算 算法 Java
Java中的Fork/Join框架详解
Fork/Join框架是Java并行计算的强大工具,尤其适用于需要将任务分解为子任务的场景。通过正确使用Fork/Join框架,可以显著提升应用程序的性能和响应速度。在实际应用中,应结合具体需求选择合适的任务拆分策略,以最大化并行计算的效率。
65 23
|
4月前
|
人工智能 前端开发 Java
基于开源框架Spring AI Alibaba快速构建Java应用
本文旨在帮助开发者快速掌握并应用 Spring AI Alibaba,提升基于 Java 的大模型应用开发效率和安全性。
580 24
基于开源框架Spring AI Alibaba快速构建Java应用
|
4月前
|
存储 缓存 安全
Java 集合框架优化:从基础到高级应用
《Java集合框架优化:从基础到高级应用》深入解析Java集合框架的核心原理与优化技巧,涵盖列表、集合、映射等常用数据结构,结合实际案例,指导开发者高效使用和优化Java集合。
84 4

热门文章

最新文章