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
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:
Phản hồi từ học viên
5
(Dựa trên đánh giá ngày hôm nay)