By GokiSoft.com| 10:23 05/08/2022|
Spring MVC

[Video] Tìm hiểu cookie qua ví dụ - Đăng ký + đăng nhập tài khoản người dùng - C2010G BT3026



Nội dung học:
	- CRUD
	- Tìm hiểu về Cookie & Session

Phát triển 1 dự án mini project:
	Quản lý người dùng + login + register
	Ứng dụng cookie -> Keep được login

	Chức năng sẽ phát triển
		- login.html -> TH người dùng chưa login -> redirect sang trang quản lý người dung
		- register.html -> Như trên
		- index.html -> Hiển thị danh sách người
	Xử lý đơn giản -> Để hiểu về cookie -> Đáp ứng bài thi
		- login_flag = id người dung -> hack
	Xử lý nâng cao -> Áp dụng trong dự án thât

Các bước phát triển dự án:
B1) Thiết kế CSDL:
create table users (
	id int primary key auto_increment,
	fullname varchar(30),
	email varchar(150),
	password varchar(32),
	created_at datetime,
	updated_at datetime,
	deleted tinyint(1) default 0,
	active tinyint(1) default 1
)

md5: 123456
	-> e10adc3949ba59abbe56e057f20f883e
	-> Hihd2*^*7324hdsfjh(4)sdh
	-> e10adc3949ba59abbe56e057f20f883eHihd2*^*7324hdsfjh(4)sdh
	-> dc67395f49bedd70875267ce17dbe099

B2) Tao du an -> DONE
B3) Phan tich du an -> Route / Controller / Views
- UserController
- Route
	login.html
		- /login.html
		- UserController@login
		- login thanh -> login_flag = ???
	register.html
		- /register.html
		- UserController@register
	index.html
		- users/index.html
		- UserController@index
	...

- Xu ly logic trc
- Quay sang xu ly -> Auth

Để đảm bảo về bảo mật tài khoản người dùng:
	Login
		-> That bai -> OK
		-> Thanh cong
			-> gen token
				-> Day ve cookie
				-> Dua vao token -> xac dinh dc tai khoan nguoi nay la ai???
				-> Luu token-> mapping -> tai khoan nguoi dung tren server
				Xac thuc: token (cookie) <-> verify <-> server -> Xac dinh tai khoan -> login

create table user_tokens (
	id_user int references users(id),
	token varchar(32),
	primary key(id_user, token)
)




#index.jsp


<%-- 
    Document   : index
    Created on : Aug 3, 2022, 8:42:49 AM
    Author     : Administrator
--%>

<%@page contentType="text/html" pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<!DOCTYPE html>
<html>
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
        <title>User List</title>
        <meta charset="utf-8"/>
        <meta name="viewport" content="width=device-width, initial-scale=1"/>

        <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.4.1/css/bootstrap.min.css"/>
        <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.6.0/jquery.min.js"></script>
        <script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.4.1/js/bootstrap.min.js"></script>
    </head>
    <body>
        <div class="container">
            <h1 style="text-align: center">User List (${user.fullname})</h1>
            <button class="btn btn-success" style="margin-bottom: 20px">Add new user</button>
            <table class="table table-hovered">
                <thead>
                    <tr>
                        <th style="width: 50px">STT</th>
                        <th>Full Name</th>
                        <th>Email</th>
                        <th>Updated At</th>
                        <th style="width: 50px"></th>
                        <th style="width: 50px"></th>
                    </tr>
                </thead>
                <tbody>
                    <c:forEach items="${userList}" var="item" varStatus="loop">
                        <tr>
                            <td>${loop.index + 1}</td>
                            <td>${item.fullname}</td>
                            <td>${item.email}</td>
                            <td>${item.updatedAt}</td>
                            <td>
                                <button class="btn btn-warning">Edit</button>
                            </td>
                            <td>
                                <button class="btn btn-danger">Delete</button>
                            </td>
                        </tr>
                    </c:forEach>
                </tbody>
            </table>
        </div>
    </body>
</html>


#login.jsp


<%-- 
    Document   : add
    Created on : Aug 3, 2022, 8:42:58 AM
    Author     : Administrator
--%>

<%@page contentType="text/html" pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<!DOCTYPE html>
<html>
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
        <title>Login Page</title>
        <meta charset="utf-8"/>
        <meta name="viewport" content="width=device-width, initial-scale=1"/>

        <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.4.1/css/bootstrap.min.css"/>
        <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.6.0/jquery.min.js"></script>
        <script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.4.1/js/bootstrap.min.js"></script>
    </head>
    <body>
        <div class="container">
            <h1 style="text-align: center">Login</h1>
            <div class="row">
                <div class="col-md-12">
                    <form method="post" action="login.html">
                        <div class="form-group">
                            <label>Email: </label>
                            <input required="true" type="email" name="email" class="form-control" placeholder="Enter email"/>
                        </div>
                        <div class="form-group">
                            <label>Password </label>
                            <input required="true" type="password" name="pwd" class="form-control" placeholder="Enter password"/>
                        </div>
                        <p style="margin-top: 20px">
                            <a href="register.html">Create a new account</a>
                        </p>
                        <button class="btn btn-success">Login</button>
                    </form>
                </div>
            </div>
        </div>
    </body>
</html>


#register.jsp


<%-- 
    Document   : add
    Created on : Aug 3, 2022, 8:42:58 AM
    Author     : Administrator
--%>

<%@page contentType="text/html" pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<!DOCTYPE html>
<html>
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
        <title>Register Page</title>
        <meta charset="utf-8"/>
        <meta name="viewport" content="width=device-width, initial-scale=1"/>

        <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.4.1/css/bootstrap.min.css"/>
        <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.6.0/jquery.min.js"></script>
        <script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.4.1/js/bootstrap.min.js"></script>
    </head>
    <body>
        <div class="container">
            <h1 style="text-align: center">Register Form</h1>
            <div class="row">
                <div class="col-md-12">
                    <form method="post" action="register.html">
                        <div class="form-group">
                            <label>Full Name: </label>
                            <input required="true" type="text" name="fullname" class="form-control" placeholder="Enter fullname"/>
                        </div>
                        <div class="form-group">
                            <label>Email: </label>
                            <input required="true" type="email" name="email" class="form-control" placeholder="Enter email"/>
                        </div>
                        <div class="form-group">
                            <label>Password </label>
                            <input required="true" type="password" name="pwd" class="form-control" placeholder="Enter password"/>
                        </div>
                        <p style="margin-top: 20px">
                            <a href="login.html">I have a account</a>
                        </p>
                        <button class="btn btn-success">Register</button>
                    </form>
                </div>
            </div>
        </div>
    </body>
</html>


#Utility.java


/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package com.gokisoft.utils;

/**
 *
 * @author Administrator
 */
public class Utility {

    public static String getSecurityMD5(String pwd) {
        pwd = md5(pwd);
        String KEY = "Hihd2*^*7324hdsfjh(4)sdh";
        pwd = md5(pwd + KEY);
        
        return pwd;
    }
    
    public static String md5(String str) {
        try {
            java.security.MessageDigest md = java.security.MessageDigest.getInstance("MD5");
            byte[] array = md.digest(str.getBytes());
            StringBuffer sb = new StringBuffer();
            for (int i = 0; i < array.length; ++i) {
                sb.append(Integer.toHexString((array[i] & 0xFF) | 0x100).substring(1, 3));
            }
            return sb.toString();
        } catch (java.security.NoSuchAlgorithmException e) {
        }
        return null;
    }
}


#Users.java


/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package com.gokisoft.entities;

import java.io.Serializable;
import java.util.Date;
import javax.persistence.Basic;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.NamedQueries;
import javax.persistence.NamedQuery;
import javax.persistence.Table;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;
import javax.xml.bind.annotation.XmlRootElement;

/**
 *
 * @author Administrator
 */
@Entity
@Table(name = "users")
@XmlRootElement
@NamedQueries({
    @NamedQuery(name = "Users.findAll", query = "SELECT u FROM Users u")
    , @NamedQuery(name = "Users.findById", query = "SELECT u FROM Users u WHERE u.id = :id")
    , @NamedQuery(name = "Users.findByFullname", query = "SELECT u FROM Users u WHERE u.fullname = :fullname")
    , @NamedQuery(name = "Users.findByEmail", query = "SELECT u FROM Users u WHERE u.email = :email")
    , @NamedQuery(name = "Users.findByLogin", query = "SELECT u FROM Users u WHERE u.email = :email and u.password = :password")
    , @NamedQuery(name = "Users.findByPassword", query = "SELECT u FROM Users u WHERE u.password = :password")
    , @NamedQuery(name = "Users.findByCreatedAt", query = "SELECT u FROM Users u WHERE u.createdAt = :createdAt")
    , @NamedQuery(name = "Users.findByUpdatedAt", query = "SELECT u FROM Users u WHERE u.updatedAt = :updatedAt")
    , @NamedQuery(name = "Users.findByDeleted", query = "SELECT u FROM Users u WHERE u.deleted = :deleted")
    , @NamedQuery(name = "Users.findByActive", query = "SELECT u FROM Users u WHERE u.active = :active")})
public class Users implements Serializable {

    private static final long serialVersionUID = 1L;
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Basic(optional = false)
    @Column(name = "id")
    private Integer id;
    @Column(name = "fullname")
    private String fullname;
    @Column(name = "email")
    private String email;
    @Column(name = "password")
    private String password;
    @Column(name = "created_at")
    @Temporal(TemporalType.TIMESTAMP)
    private Date createdAt;
    @Column(name = "updated_at")
    @Temporal(TemporalType.TIMESTAMP)
    private Date updatedAt;
    @Column(name = "deleted")
    private Boolean deleted;
    @Column(name = "active")
    private Boolean active;

    public Users() {
    }

    public Users(Integer id) {
        this.id = id;
    }

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getFullname() {
        return fullname;
    }

    public void setFullname(String fullname) {
        this.fullname = fullname;
    }

    public String getEmail() {
        return email;
    }

    public void setEmail(String email) {
        this.email = email;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public Date getCreatedAt() {
        return createdAt;
    }

    public void setCreatedAt(Date createdAt) {
        this.createdAt = createdAt;
    }

    public Date getUpdatedAt() {
        return updatedAt;
    }

    public void setUpdatedAt(Date updatedAt) {
        this.updatedAt = updatedAt;
    }

    public Boolean getDeleted() {
        return deleted;
    }

    public void setDeleted(Boolean deleted) {
        this.deleted = deleted;
    }

    public Boolean getActive() {
        return active;
    }

    public void setActive(Boolean active) {
        this.active = active;
    }

    @Override
    public int hashCode() {
        int hash = 0;
        hash += (id != null ? id.hashCode() : 0);
        return hash;
    }

    @Override
    public boolean equals(Object object) {
        // TODO: Warning - this method won't work in the case the id fields are not set
        if (!(object instanceof Users)) {
            return false;
        }
        Users other = (Users) object;
        if ((this.id == null && other.id != null) || (this.id != null && !this.id.equals(other.id))) {
            return false;
        }
        return true;
    }

    @Override
    public String toString() {
        return "com.gokisoft.controller.Users[ id=" + id + " ]";
    }
    
}


#UserTokens.java


/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package com.gokisoft.entities;

import java.io.Serializable;
import javax.persistence.EmbeddedId;
import javax.persistence.Entity;
import javax.persistence.NamedQueries;
import javax.persistence.NamedQuery;
import javax.persistence.Table;
import javax.xml.bind.annotation.XmlRootElement;

/**
 *
 * @author Administrator
 */
@Entity
@Table(name = "user_tokens")
@XmlRootElement
@NamedQueries({
    @NamedQuery(name = "UserTokens.findAll", query = "SELECT u FROM UserTokens u")
    , @NamedQuery(name = "UserTokens.findByIdUser", query = "SELECT u FROM UserTokens u WHERE u.userTokensPK.idUser = :idUser")
    , @NamedQuery(name = "UserTokens.findByToken", query = "SELECT u FROM UserTokens u WHERE u.userTokensPK.token = :token")})
public class UserTokens implements Serializable {

    private static final long serialVersionUID = 1L;
    @EmbeddedId
    protected UserTokensPK userTokensPK;

    public UserTokens() {
    }

    public UserTokens(UserTokensPK userTokensPK) {
        this.userTokensPK = userTokensPK;
    }

    public UserTokens(int idUser, String token) {
        this.userTokensPK = new UserTokensPK(idUser, token);
    }

    public UserTokensPK getUserTokensPK() {
        return userTokensPK;
    }

    public void setUserTokensPK(UserTokensPK userTokensPK) {
        this.userTokensPK = userTokensPK;
    }

    @Override
    public int hashCode() {
        int hash = 0;
        hash += (userTokensPK != null ? userTokensPK.hashCode() : 0);
        return hash;
    }

    @Override
    public boolean equals(Object object) {
        // TODO: Warning - this method won't work in the case the id fields are not set
        if (!(object instanceof UserTokens)) {
            return false;
        }
        UserTokens other = (UserTokens) object;
        if ((this.userTokensPK == null && other.userTokensPK != null) || (this.userTokensPK != null && !this.userTokensPK.equals(other.userTokensPK))) {
            return false;
        }
        return true;
    }

    @Override
    public String toString() {
        return "com.gokisoft.entities.UserTokens[ userTokensPK=" + userTokensPK + " ]";
    }
    
}


#UserTokensPK.java


/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package com.gokisoft.entities;

import java.io.Serializable;
import javax.persistence.Basic;
import javax.persistence.Column;
import javax.persistence.Embeddable;

/**
 *
 * @author Administrator
 */
@Embeddable
public class UserTokensPK implements Serializable {

    @Basic(optional = false)
    @Column(name = "id_user")
    private int idUser;
    @Basic(optional = false)
    @Column(name = "token")
    private String token;

    public UserTokensPK() {
    }

    public UserTokensPK(int idUser, String token) {
        this.idUser = idUser;
        this.token = token;
    }

    public int getIdUser() {
        return idUser;
    }

    public void setIdUser(int idUser) {
        this.idUser = idUser;
    }

    public String getToken() {
        return token;
    }

    public void setToken(String token) {
        this.token = token;
    }

    @Override
    public int hashCode() {
        int hash = 0;
        hash += (int) idUser;
        hash += (token != null ? token.hashCode() : 0);
        return hash;
    }

    @Override
    public boolean equals(Object object) {
        // TODO: Warning - this method won't work in the case the id fields are not set
        if (!(object instanceof UserTokensPK)) {
            return false;
        }
        UserTokensPK other = (UserTokensPK) object;
        if (this.idUser != other.idUser) {
            return false;
        }
        if ((this.token == null && other.token != null) || (this.token != null && !this.token.equals(other.token))) {
            return false;
        }
        return true;
    }

    @Override
    public String toString() {
        return "com.gokisoft.entities.UserTokensPK[ idUser=" + idUser + ", token=" + token + " ]";
    }
    
}


#UserController.java


/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package com.gokisoft.controller;

import com.gokisoft.entities.UserTokens;
import com.gokisoft.entities.UserTokensPK;
import com.gokisoft.entities.Users;
import com.gokisoft.utils.Utility;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;
import javax.persistence.Query;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.CookieValue;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;

/**
 *
 * @author Administrator
 */
@Controller
@RequestMapping(value = "/")
public class UserController {
    EntityManagerFactory factory;
    EntityManager manager;
    
    @RequestMapping(value = "/login", method = RequestMethod.GET)
    public String login(HttpServletRequest request) {
//        String loginFlag = getCookie(request.getCookies(), "login_flag");
//        
//        if(loginFlag != null && !loginFlag.isEmpty()) {
//            return "redirect:users/index.html";
//        }
        Users u = auth(request);
        if(u != null) {
            return "redirect:users/index.html";
        }
        
        return "user/login";
    }
    
    @RequestMapping(value = "/login", method = RequestMethod.POST)
    public String confirmLogin(@RequestParam HashMap<String, String> formData, HttpServletResponse response) {
        String email = formData.get("email");
        String pwd = formData.get("pwd");
        
        //Chuyen pwd -> md5
        pwd = Utility.getSecurityMD5(pwd);
        
        connect();
        
        Query query = manager.createNamedQuery("Users.findByLogin", Users.class);
        query.setParameter("email", email);
        query.setParameter("password", pwd);
        
        List<Users> userList = query.getResultList();
        
        if(userList != null && userList.size() > 0) {
            //Login thanh cong
            //Cai login_flag = ???
//            Cookie cookie = new Cookie("login_flag", userList.get(0).getId() + "");
//            response.addCookie(cookie);
            String token = Utility.getSecurityMD5(userList.get(0).getEmail() + System.currentTimeMillis());
            response.addCookie(new Cookie("token", token));
            
            //Luu vao database
            UserTokens userTokens = new UserTokens();
            UserTokensPK userTokensPK = new UserTokensPK(userList.get(0).getId(), token);
            userTokens.setUserTokensPK(userTokensPK);
            
            manager.getTransaction().begin();
            manager.persist(userTokens);
            manager.getTransaction().commit();
            
            return "redirect:users/index.html";
        }
        
        return "redirect:login.html";
    }
    
    @RequestMapping(value = "/register", method = RequestMethod.GET)
    public String register(HttpServletRequest request) {
//        String loginFlag = getCookie(request.getCookies(), "login_flag");
//        
//        if(loginFlag != null && !loginFlag.isEmpty()) {
//            return "redirect:users/index.html";
//        }
        Users u = auth(request);
        if(u != null) {
            return "redirect:users/index.html";
        }
        
        return "user/register";
    }
    
    @RequestMapping(value = "/register", method = RequestMethod.POST)
    public String doRegister(@RequestParam HashMap<String, String> formData) {
        String email = formData.get("email");
        String pwd = formData.get("pwd");
        String fullname = formData.get("fullname");
        
        //Check xem email da ton tai chua
        connect();
        Query query = manager.createNamedQuery("Users.findByEmail", Users.class);
        query.setParameter("email", email);
        
        List<Users> userList = query.getResultList();
        if(userList != null && userList.size() > 0) {
            return "redirect:register.html";
        }
        
        //Chuyen pwd -> md5
        pwd = Utility.getSecurityMD5(pwd);
        
        Users u = new Users();
        u.setFullname(fullname);
        u.setEmail(email);
        u.setPassword(pwd);
        u.setCreatedAt(new Date());
        u.setUpdatedAt(new Date());
        
        manager.getTransaction().begin();
        manager.persist(u);
        manager.getTransaction().commit();
        
        return "redirect:login.html";
    }
    
    @RequestMapping(value = "/users/index", method = RequestMethod.GET)
    public String index(HttpServletRequest request, ModelMap modelMap) {
//        String loginFlag = getCookie(request.getCookies(), "login_flag");
//        
//        if(loginFlag == null || loginFlag.isEmpty()) {
//            return "redirect:../login.html";
//        }
        Users u = auth(request);
        if(u == null) {
            return "redirect:../login.html";
        }
        
        connect();
        
        Query q = manager.createNamedQuery("Users.findAll", Users.class);
        List<Users> userList = q.getResultList();
        
        modelMap.addAttribute("userList", userList);
        modelMap.addAttribute("user", u);
        
        return "user/index";
    }
    
    Users auth(HttpServletRequest request) {
        String token = getCookie(request.getCookies(), "token");
        
        connect();
        
        Query q = manager.createNamedQuery("UserTokens.findByToken", UserTokens.class);
        q.setParameter("token", token);
        
        List<UserTokens> list = q.getResultList();
        
        if(list.size() > 0) {
            int id = list.get(0).getUserTokensPK().getIdUser();
            q = manager.createNamedQuery("Users.findById", Users.class);
            q.setParameter("id", id);
            
            return (Users) q.getSingleResult();
        }
        
        return null;
    }
    
    String getCookie(Cookie[] cookies, String key) {
        for (Cookie cookie : cookies) {
            if(cookie.getName().equalsIgnoreCase(key)) {
                return cookie.getValue();
            }
        }
        return "";
    }
    
    void connect() {
        if(factory == null || !factory.isOpen()) {
            factory = Persistence.createEntityManagerFactory("SpringMVCPU");
            manager = factory.createEntityManager();
        }
    }
}


Tags:

Liên kết rút gọn:

https://gokisoft.com/3026

Bình luận