网站登录的流程和逻辑
01、图解
01、在templates新建一个login.html
同时把login.css的css/js/img放入到static目录下:
02、定义LoginController跳转login.html
package com.li.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
@Controller
public class LoginController {
@GetMapping("/login")
public String login() {
return "login";
}
}
03、浏览器访问http://localhost:8888/login
02、登录逻辑交互
01、打开login.html,引入vue/axios的js文件如下
<script src="/js/vue.min.js"></script>
<script src="/js/axios.min.js"></script>
<script src="/js/login/login.js"></script>
02、定义login.js初始化vue实例
var vue = new Vue({
el:"#app",
data:{
title:"MoMo登录"
}
});
03、编写登录的具体触发事件
注意:在刚开始的时候,不要考虑什么验证,数据合法性等。这些东西一定要在开发完毕或者差不多的时候,在去考虑数据合法性。
一定先学会做核心功能
- 获取用户输入的账号和密码=
- 然后传递到后台
- 通过账号查询你用户信息
- 根据查询的用户信息的密码和你输入的密码进行匹配
- 如果匹配成功,说明登录有效,并且把用户信息放入到session中进行记录。
- 如果匹配是不,说明用户名和密码错误,给前端进行提示
- 然后在考虑各种数据的安全性和有效性
- 然后在考虑增加验证码或者验证码
- 可以考虑使用短信登录
- 在去考虑使用手机号码登录,昵称等,账号等等
- 登录限制(黑白名单)
在login.js中定义登录按钮触发的事件:
var vue = new Vue({
el:"#app",
data:{
title:"MoMo登录",
user:{
account:"",
password:""
}
},
methods:{
toLogin:function(){
var that = this;
var user = that.user;
alert(JSON.stringify(user))
}
}
});
一定测试打印
04、定义后台的处理接受参数的UserVo
package com.li;
import lombok.Data;
@Data
public class UserVo {
private String account;
private String password;
private String code;
}
具体的页面登录代码如下:
package com.li.controller;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.li.UserVo;
import com.li.entity.User;
import com.li.service.user.IUserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.ResponseBody;
import javax.servlet.http.HttpSession;
@Controller
public class LoginController {
@Autowired
private IUserService userService;
@PostMapping("/logined")
@ResponseBody
public String logined(@RequestBody UserVo userVo, HttpSession session) {
LambdaQueryWrapper<User> lambdaQueryWrapper = new LambdaQueryWrapper<>();
lambdaQueryWrapper.eq(User::getTelephone, userVo.getAccount());
User user = userService.getOne(lambdaQueryWrapper);
if (user == null) {
return "fail";
}
if (user.getPassword().equals(userVo.getPassword())) {
session.setAttribute("sessionuser", user);
return "success";
}
return "fail";
}
}
前端js处理代码
var vue = new Vue({
el:"#app",
data:{
title:"MoMo登录",
user:{
account:"10000",
password:"123456",
code:""
}
},
methods:{
toLogin:function(){
var that = this;
var user = that.user;
axios.post("/logined",user).then(function(res){
if(res.data == "success"){
window.location.href = "/";
}else{
alert("输入账号密码有误");
document.getElementById("pwd").value = "";
document.getElementById("pwd").focus();
}
})
}
}
});
这里就完成了登录逻辑。
-
注意问题:现在使用axios的post处理业务,post传递给服务器端参数的时候,一定是要用对象,并且这个对象参数的前面一定要增加@RequestBody。 @PostMapping("/logined")
@ResponseBody
public String logined(@RequestBody UserVo userVo);
否则你拿不到,千万不要写如下代码 @PostMapping("/logined")
@ResponseBody
public String logined(String account,String password);
如果不明白看官网文档:http://www.axios-js.com/zh-cn/docs/ -
注意问题2:请记住,当前的LoginController是一个@Controller. 这个注解类中既有登录页面的跳转,又有异步逻辑的处理,你的处理登录的逻辑请记住一定要加@ResponseBody注解。
05、改进代码 – 密码加密
在项目的包中新建一个utils包,放入pwd/MdUtil.java密码加密的工具类:
package com.li.utils.pwd;
import java.math.BigInteger;
import java.security.MessageDigest;
public class MD5Util {
public MD5Util() {
}
public static String md5(String str) {
try {
MessageDigest md5 = MessageDigest.getInstance("MD5");
md5.update(str.getBytes("UTF-8"));
return bytesToHex(md5.digest());
} catch (Exception var2) {
throw new RuntimeException(var2);
}
}
public static String md5slat(String str){
return MD5Util.md5(MD5Util.md5("li"+str+"202102170318!!!"));
}
public static String bytesToHex(byte[] bytes) {
BigInteger bigInt = new BigInteger(1, bytes);
String hashtext;
for(hashtext = bigInt.toString(16); hashtext.length() < 32; hashtext = "0" + hashtext) {
}
return hashtext;
}
public static void main(String[] args) {
System.out.println(md5slat("123456"));
}
}
运行main函数,把生成的密码修改到数据中。然后开始去校验输入的密码是否和数据库加密一致,如下:
package com.li.controller;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.li.UserVo;
import com.li.entity.User;
import com.li.service.user.IUserService;
import com.li.utils.pwd.MD5Util;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.ResponseBody;
import javax.servlet.http.HttpSession;
@Controller
public class LoginController {
@Autowired
private IUserService userService;
@GetMapping("/login")
public String login() {
return "login";
}
@ResponseBody
@PostMapping("/logined")
public String logined(@RequestBody UserVo userVo, HttpSession session) {
LambdaQueryWrapper<User> lambdaQueryWrapper = new LambdaQueryWrapper<>();
lambdaQueryWrapper.eq(User::getTelephone, userVo.getAccount());
User user = userService.getOne(lambdaQueryWrapper);
if (user == null) {
return "fail";
}
String inputpwd = MD5Util.md5slat(userVo.getPassword());
if (user.getPassword().equals(inputpwd)) {
session.setAttribute("sessionuser", user);
return "success";
}
return "fail";
}
}
06、改进代码–登录以后不能在登录
- 如果一个用户已经登录,如果在进入登录页面,直接进入首页
@GetMapping("/login")
public String login(HttpSession session) {
User user = (User)session.getAttribute(KConstants.SESSION_USER);
if(user!=null){
return "redirect:/";
}
return "login";
}
07、改进代码–如果用户直接访问首页需要登录才能进入怎么处理呢?
@GetMapping(value = {"/", "/index"})
public ModelAndView index(String cid, HttpSession session) {
ModelAndView modelAndView = new ModelAndView();
User user = (User)session.getAttribute(KConstants.SESSION_USER);
if(user==null){
modelAndView.setViewName("redirect:/login");
return modelAndView;
}
modelAndView.addObject("blogCategories", blogCategoryService.findBlogCategies());
modelAndView.addObject("cid", Optional.ofNullable(cid).orElse("0"));
modelAndView.setViewName("index");
return modelAndView;
}
未来特别是在做个人中心,后台的时候,大部分情况都是一定登录的,所以如果每个地方都去做这这样的判断就显得很鸡肋,所以后面必须要使用:拦截器来进行统一处理。后续进行。
08、改进代码—关于登录用户渲染到用户问题
08-01、第一个解决方案:直接用freemarker语法进行渲染
定义一个公共的头部如下:
内容如下:
<div style="height: 50px;line-height: 50px;background: #fff;text-align: center;color:#333">
当前登录的用户是:${sessionuser.nickname} <a href="/logout">退出</a>
</div>
头部页面进行包含
在index.html和detail.html需要进行头部页面包含即可:
<#include "/common/header.html"/>
08-02、第二种用异步axios
第一步:定义个js/common/common.js
第二步:后端定义一个接口返回session用户信息
/**
* 异步获取session中用户信息
*
* @return
*/
@PostMapping("/login/loadsession")
@ResponseBody
public User toSessionUser(HttpSession session) {
return (User) session.getAttribute(KConstants.SESSION_USER);
}
第三步:每个页面都也如common.js
09、改进代码—关于退出
@GetMapping("/logout")
public String logout(HttpSession session) {
session.invalidate();
return "redirect:/login";
}
```java
@ResponseBody
public User toSessionUser(HttpSession session) {
return (User) session.getAttribute(KConstants.SESSION_USER);
}
|