Java - 基于Session的简单登录

in TCEHJava with 0 comment

一、Session简介

此文不再介绍Session,其介绍及原理请访问《理解Cookie和Session机制

二、基于Session的简单登录示例

说明:

  本示例将使用原始HttpServlet的方式来实现,能更加清晰的理解该功能。商业开发普遍使用类似spring等框架,更易开发和维护项目。

项目结构:

1.jpg

相关代码如下:

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>
Comments are closed.