Session简介
此文不再介绍Session,其介绍及原理请访问《理解Cookie和Session机制》
基于Session的简单登录示例
说明:
本示例将使用原始HttpServlet的方式来实现,能更加清晰的理解该功能。商业开发普遍使用类似spring等框架,更易开发和维护项目。
项目结构:
相关代码如下:
IndexController.java
package com.back.Controller;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import com.back.entity.User;
/**
* 主页
*
* @author Back
*
*/
public class IndexController extends HttpServlet {
private static final long serialVersionUID = 6020727692785439128L;
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
HttpSession session = req.getSession();
if (session != null) {
// session数据是存储在服务器上的,客户端仅仅存储JsessionId,因此是相对安全的。
User user = (User) session.getAttribute("User");
if (user != null) {
System.err.println("sessionId="+session.getId());
// 登录成功
String useName = user.getUserName();
req.setAttribute("useName", useName);
req.getRequestDispatcher("/WEB-INF/index.jsp").forward(req, resp);
return;
}
}
req.getRequestDispatcher("/login.jsp").forward(req, resp);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
LoginController.java
package com.back.Controller;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import com.back.entity.User;
import com.back.service.LoginService;
public class LoginController extends HttpServlet {
private static final long serialVersionUID = 8584564762024384848L;
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
super.doGet(req, resp);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String userAcc = req.getParameter("useAcc");
String userPwd = req.getParameter("usePwd");
String timeOut = req.getParameter("timeOut");
// 此处应做些数据校验。
User user = LoginService.loginService.login(userAcc, userPwd);
if (user != null) {
HttpSession session = req.getSession(true);
session.setAttribute("User", user);
session.setMaxInactiveInterval(Integer.valueOf(timeOut));
// 登陆成功
resp.getWriter().write("{\"respCode\":\"200\"}");
} else {
// 登陆失败
resp.getWriter().write("{\"respCode\":\"401\"}");
}
}
}
LogoutController.java
package com.back.Controller;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class LogoutController extends HttpServlet {
private static final long serialVersionUID = 1189917317247780316L;
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//注销登陆
req.getSession().invalidate();
resp.sendRedirect("/web");
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// TODO Auto-generated method stub
doGet(req, resp);
}
}
User.java
package com.back.entity;
/**
* 用户实体
*
* @author Back
*
*/
public class User {
private Integer userId;
private String userName;
private String userAcc;
private String userPwd;
public Integer getUserId() {
return userId;
}
public void setUserId(Integer userId) {
this.userId = userId;
}
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public String getUserAcc() {
return userAcc;
}
public void setUserAcc(String userAcc) {
this.userAcc = userAcc;
}
public String getUserPwd() {
return userPwd;
}
public void setUserPwd(String userPwd) {
this.userPwd = userPwd;
}
@Override
public String toString() {
return "User [userId=" + userId + ", userName=" + userName + ", userAcc=" + userAcc + ", userPwd=" + userPwd
+ "]";
}
}
LoginFilter.java
package com.back.filter;
import java.io.IOException;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import com.back.entity.User;
/**
* 网络上大部分教程都没有提及过滤器这一块。一个完整的用户登录,必须需要过滤器或拦截器来过滤所有请求。
* 防止恶意用户在知道请求路径的情况下,未登录访问未授权访问资源
* @author Back
*
*/
public class LoginFilter implements Filter {
@Override
public void destroy() {
// TODO Auto-generated method stub
}
@Override
public void doFilter(ServletRequest arg0, ServletResponse arg1, FilterChain arg2)
throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest) arg0;
HttpServletResponse response = (HttpServletResponse) arg1;
HttpSession session = request.getSession();
String url = request.getRequestURI();
boolean isLogin = false;
System.err.println(url);
if (null != session) {
User user = (User) session.getAttribute("User");
if (null != user) {
// 已登录
isLogin = true;
arg2.doFilter(arg0, arg1);
}
}
if (!isLogin) {
//不过滤主页及登录接口
if ("/web/".equals(url) || "/web/login".equals(url)) {
arg2.doFilter(arg0, arg1);
} else {
//重定向至主界面,及回到登录模块
response.sendRedirect("/web");
}
}
}
@Override
public void init(FilterConfig arg0) throws ServletException {
// TODO Auto-generated method stub
}
}
LoginService.java
package com.back.service;
import java.util.ArrayList;
import java.util.List;
import com.back.entity.User;
public class LoginService {
public static LoginService loginService = new LoginService();
public User login(String userAcc, String userPwd) {
//实际操作中的账户信息应从数据库取,并比较其存储的密码摘要信息,不可明文存储
List<User> users = new ArrayList<>();
User user = new User();
user.setUserId(0);
user.setUserName("小红");
user.setUserAcc("xiaohong");
user.setUserPwd("xiaohong");//此处可以用MD5等摘要算法,存储签名即可
User user1 = new User();
user1.setUserId(1);
user1.setUserName("小黄");
user1.setUserAcc("xiaohuang");
user1.setUserPwd("xiaohuang");//此处可以用MD5等摘要算法,存储签名即可
User user2 = new User();
user2.setUserId(2);
user2.setUserName("小蓝");
user2.setUserAcc("xiaolan");
user2.setUserPwd("xiaolan");//此处可以用MD5等摘要算法,存储签名即可
users.add(user);
users.add(user1);
users.add(user2);
for (int i = 0; i < users.size(); i++) {
String acc = users.get(i).getUserAcc();
String pwd = users.get(i).getUserPwd();
//账户密码相同,即可登录
if (acc.equals(userAcc)&&pwd.equals(userPwd)) {
return users.get(i);
}
}
return null;
}
}
index.jsp
<%@ page language="java" pageEncoding="UTF-8" isErrorPage="false"%>
<%
String useName = (String) request.getAttribute("useName");
%>
登录成功!
欢迎您,<%=useName %>!
<a href="http://localhost:8080/web/logout">注销</a>
web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
id="WebApp_ID" version="3.1">
<display-name>web</display-name>
<welcome-file-list>
<!-- <welcome-file>index.html</welcome-file>
<welcome-file>index.htm</welcome-file> -->
<welcome-file>index.jsp</welcome-file>
<welcome-file>default.html</welcome-file>
<welcome-file>default.htm</welcome-file>
<welcome-file>default.jsp</welcome-file>
</welcome-file-list>
<filter>
<filter-name>Login</filter-name>
<filter-class>com.back.filter.LoginFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>Login</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<servlet>
<servlet-name>Login</servlet-name>
<servlet-class>com.back.Controller.LoginController</servlet-class>
</servlet>
<servlet>
<servlet-name>Logout</servlet-name>
<servlet-class>com.back.Controller.LogoutController</servlet-class>
</servlet>
<servlet>
<servlet-name>Index</servlet-name>
<servlet-class>com.back.Controller.IndexController</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>Login</servlet-name>
<url-pattern>/login</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>Logout</servlet-name>
<url-pattern>/logout</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>Index</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
</web-app>
login.jsp
<%@ page language="java" pageEncoding="UTF-8" isErrorPage="false"%>
<table>
<tr>
<td>账号:</td>
<td><input type="text" name="account" id="account" style="width: 200px;"></td>
</tr>
<tr>
<td>密码:</td>
<td><input type="password" name="password" id = "password"></td>
</tr>
<tr>
<td>有效期:</td>
<td><input type="radio" name="timeout" value="-1" checked>关闭浏览器即失效<br />
<input type="radio" name="timeout" value="10">10秒钟内有效<br />
<input type="radio" name="timeout" value="<%=30 * 24 * 60 * 60%>"> 30天 内有效 <br />
<input type="radio" name="timeout" value="<%=Integer.MAX_VALUE%>"> 永久有效 <br /></td>
</tr>
<tr>
<td></td>
<td><button onclick="todo();">登录</button></td>
<td></td>
</tr>
<tr>
<td></td>
<td><font id="msg" size="20px" color="red"></font></td>
<td></td>
</tr>
</table>
<script src="http://libs.baidu.com/jquery/2.1.1/jquery.min.js"></script>
<script>
function todo() {
var account = $('#account').val();
var password = $('#password').val();
var timeOut = $('input:radio:checked').val();
var data = "useAcc="+account+"&usePwd="+password+"&timeOut="+timeOut;
$.ajax({
type : "POST",
url : "http://localhost:8080/web/login",
dataType : "json", //数据格式设置为json
data : data,
success : function(data) { //成功的回调函数
if(data.respCode==401){
$('#msg').html("登陆失败!!!");
}
if(data.respCode==200){
//因使用ajax请求后台,仅获取数据,登录成功后,请求转发和重定向均会失败。
//request.getRequestDispatcher().forward();
//response.sendRedirect();
//因此,登录成功需刷新界面或用js打开相应页面
window.location.reload();
}
},
error : function(e) {
console.log(e);
}
});
}
</script>
本文由 Administrator 创作,采用 知识共享署名4.0 国际许可协议进行许可
本站部分文章采集自互联网,因某些原因未注明出处,如有侵权,请留言告知。