SpringBootWeb 登录认证

news2024/12/24 0:35:54

登录认证,那什么是认证呢?

  • 所谓认证指的就是根据用户名和密码校验用户身份的这个过程,认证成功之后,我们才可以访问系统当中的信息,否则就拒绝访问。

在前面的案例中,我们已经实现了部门管理、员工管理的基本功能,但是大家会发现,我们并没有登录,就直接访问到了Tlias智能学习辅助系统的后台。 这是不安全的,所以我们今天的主题就是登录认证最终我们要实现的效果就是用户必须登录之后,才可以访问后台系统中的功能

  • 在登录页面中,用户要输入用户名,输入密码,然后接下来点击登录,如果输入的用户名或者密码错误,此时就会停留在登录页面当中,并且提示出对应的错误信息;
  • 如果用户名和密码都是正确的,我们点击登录按钮,此时才会进入到系统当中,进入到系统之后,我们就可以来操作系统当中的数据了。

要想实现用户登录的功能,我们需要两步操作来实现:

  1. 首先第一步,我们要先来完成最为基础的登录功能,这步操作就是来判断用户输入的用户名和密码是否正确
  2. 第二步,我们要来完成登录校验操作:登录校验指的就是当我们浏览器发起一个请求之后,服务端需要判断这个用户是否登录了,如果登录了,则执行正常的业务操作;如果没有登录,就需要跳转到登录界面,让他完成登录之后再来访问这个系统。 

注意:登录校验是整个登录功能的核心! 

1. 登录功能

1.1 需求

在登录界面中,我们可以输入用户的用户名以及密码,然后点击 "登录" 按钮就要请求服务器,服务端判断用户输入的用户名或者密码是否正确。如果正确,则返回成功结果,前端跳转至系统首页面。 

思考:在登录的时候,我们需要校验用户名和密码是否正确,这条SQL语句该怎么写?

回答:其实非常简单,逆向思考就是根据用户名和密码来查询员工,如果根据用户名和密码,我查询到了员工,就说明用户名和密码是正确的;如果根据用户名和密码,我没有查询到员工,就说明用户名或密码错误。

SQL语句:

-- 登录时校验用户名和密码
select * from emp where username = '' and password = '';

思考:根据这条SQL语句查询出来的员工有没有可能是多个?

回答:不可能,因为之前我们创建emp员工表的时候,针对于username这个字段我们添加的是unique唯一约束,所以username这个它是不可能重复的,因此最终我们查询出来的数据,最多只会有一条。

1.2 接口文档

  • 我们参照接口文档来开发登录功能

基本信息

  • 请求参数

参数格式:application/json

参数说明:

名称类型是否必须备注
usernamestring必须用户名
passwordstring必须密码

请求数据样例:

 

  • 响应数据

参数格式:application/json

参数说明:

名称类型是否必须默认值备注其他信息
codenumber必须响应码, 1 成功 ; 0 失败
msgstring非必须提示信息
datastring必须返回的数据 , jwt令牌

响应数据样例:  

1.3 登录 - 思路分析

说明:目前我们先不考虑返回JWT令牌,目前我们只是给前端响应成功还是失败。

首先第一件事,我们肯定需要在Controller当中定义一个方法来处理这个登录请求此时需要思考登录这个请求方法我们应该定义哪一个Controller当中?
是DeptController,还是EmpController,还是UploadController,都不是,原因:DeptController的请求路径是/depts,EmpController的请求路径是/emps,UploadController的请求路径是/upload,并且UploadController是用来进行文件上传的。 

因此,我们需要再定义一个Controller,专门用来处理登录请求,取名叫LoginController,然后我们在LoginController当中再来定义一个方法来处理登录的请求,由于登录的请求方式是一个POST请求,所以我们需要在该方法上面加上@PostMapping,而且请求格式的参数是一个JSON格式的请求参数,最终服务端要把JSON格式的参数封装到一个对象当中,所以我们要在方法的形参上加上@RequestBody注解来接收前端传递过来的JSON格式的数据并填充到实体类中,

登录服务端的核心逻辑就是:接收前端请求传递的用户名和密码 ,然后再根据用户名和密码查询用户信息,如果用户信息存在,则说明用户输入的用户名和密码正确。如果查询到的用户不存在,则说明用户输入的用户名和密码错误。  

1.4 功能开发

LoginController

package com.gch.controller;

import com.gch.pojo.Emp;
import com.gch.pojo.Result;
import com.gch.service.EmpService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@Slf4j
@RestController
@RequestMapping("/login")
/**
   登录功能控制器
 */
public class LoginController {
    @Autowired
    private EmpService empService;
    /**
     * 处理登录请求
     * @param emp 员工对象
     * @return 响应
     */
    @PostMapping
    public Result login(@RequestBody Emp emp) {
        // 1.记录日志
        log.info("处理该用户登录请求,username:{}, password:{}", emp.getUsername(), emp.getPassword());
        // 2.调用service进行查询,查询/校验该用户信息是否存在
        Emp e = empService.login(emp);
        // 3.响应
        return e != null ? Result.success(e) : Result.error("用户名或密码错误");
    }
}

EmpService

package com.gch.service;

import com.gch.pojo.Emp;
import com.gch.pojo.PageBean;

import java.time.LocalDate;
import java.util.List;

/**
   员工业务规则
 */
public interface EmpService {
    /**
     * 处理该用户的登录请求
     * @param emp 员工对象
     * @return 根据前端传递的用户信息返回查询到的员工对象
     */
    Emp login(Emp emp);
}

EmpServiceImpl

package com.gch.service.impl;

import com.gch.mapper.EmpMapper;
import com.gch.pojo.Emp;
import com.gch.pojo.PageBean;
import com.gch.service.EmpService;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.List;

/**
   员工业务实现类
 */
@Slf4j
@Service
public class EmpServiceImpl implements EmpService {
    @Autowired
    private EmpMapper empMapper;
    /**
     * 处理该用户的登录请求
     * @param emp 员工对象
     * @return 根据前端传递的用户信息返回查询到的员工对象
     */
    @Override
    public Emp login(Emp emp) {
        // 1.调用Mapper层查询该员工信息
        Emp loginEmp = empMapper.getByUsernameAndPassword(emp);
        // 2.返回查询结果给Controller
        return loginEmp;
    }
}

EmpMapper

package com.gch.mapper;

import com.gch.pojo.Emp;
import org.apache.ibatis.annotations.Insert;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Select;
import org.apache.ibatis.annotations.Update;

import java.time.LocalDate;
import java.util.List;

/**
   员工管理
 */
@Mapper
public interface EmpMapper {
    /**
     * 处理该用户的登录请求
     * 根据用户名和密码查询员工
     * @param emp 员工对象
     * @return 根据前端传递过来的请求参数中的用户信息查询员工是否存在
     */
    @Select("select * from tlias.emp where username = #{username} and password = #{password}")
    Emp getByUsernameAndPassword(Emp emp);
}

1.5 测试

功能开发完毕后,我们就可以启动服务,打开Postman进行测试了。

发起POST请求,访问:http://localhost:8080/login

Postman测试通过了,那接下来,我们就可以结合着前端工程进行联调测试

先退出系统,进入到登录页面:  

在登录页面输入账户密码:  

故意把密码输错,看登陆页面会不会提示错误!

注意:提示错误的信息,就是在Controller中响应给前端的信息!

 

登录成功之后进入到后台管理系统页面:  

2. 登录校验

2.1 问题分析

我们已经完成了基础登录功能的开发与测试,并且完成了前后端联调,在我们登录成功后就可以进入到后台管理系统中进行数据的操作。  

但是当我们在浏览器中新的页面上输入地址:http://localhost:9528/#/system/dept也就是复制了已经登录进入后台管理系统的页面地址,接着退出后台管理系统,然后关闭该页面,再次打开一个新的标签页,然后粘贴进入刚才已经登录进入后台管理系统的页面地址,发现没有登录仍然可以进入到后端管理系统页面。

而真正的登录功能应该是:登陆后才能访问后端系统页面,不登陆则跳转登陆页面进行登陆。 

这是异常现象!

问题:在未登录情况下,我们也可以直接访问部门管理、员工管理等功能。

为什么会出现这个问题?

  • 其实原因很简单,就是因为针对于我们当前所开发的部门管理、员工管理以及文件上传等相关接口来说,我们在服务器端并没有做任何的判断,没有去判断用户是否登录了。所以无论用户是否登录,都可以访问部门管理以及员工管理的相关数据。所以我们目前所开发的登录功能,它只是徒有其表。而我们要想解决这个问题,我们就需要完成一步非常重要的操作:登录校验。

什么是登录校验?

  • 所谓登录校验,指的是我们在服务器端接收到浏览器发送过来的请求之后,首先我们要对请求进行校验。先要校验一下用户登录了没有,如果用户已经登录了,就直接执行对应的业务操作就可以了;如果用户没有登录,此时就不允许他执行相关的业务操作,直接给前端响应一个错误的结果,最终跳转到登录页面,要求他登录成功之后,再来访问对应的数据。

了解完什么是登录校验之后,接下来我们分析一下登录校验大概的实现思路。  

首先我们在宏观上先有一个认知,然后再来逐个击破:

前面在讲解HTTP协议的时候,我们提到HTTP协议是无状态协议什么又是无状态的协议?

  • 所谓无状态指的是每一次请求都是独立的,下一次请求并不会携带上一次请求的数据。而浏览器与服务器之间进行交互,是基于HTTP协议的,也就意味着现在我们通过浏览器来访问了登陆这个接口,实现了登陆的操作,接下来我们在执行其他业务操作时,服务器也并不知道这个员工到底登陆了没有。因为HTTP协议是无状态的,两次请求之间是独立的,所以是无法判断这个员工到底登陆了没有。

那应该怎么来实现登录校验的操作呢?具体的实现思路可以分为两部分:  

  1. 在服务端要想判断这个员工是否已经登录,我们就需要在员工登录成功之后,要存储这么一个登录成功的标记,一旦员工登陆成功,那我们就存储登录成功的这样一个标记,记录用户已经登录成功的标记;
  2. 然后接下来我们在每一个接口方法执行之前,先来做一个条件判断,来判断一下这个员工到底登录了没有,如果这个员工已经登录了,那接下来,我们就执行正常的业务操作就可以了;如果这个员工没有登录,我们在这一块儿直接返回错误的信息,把这个错误的信息返回给前端,前端拿到这个错误的信息之后,它会自动的跳转到登陆页面。

我们程序中所开发的查询功能、删除功能、添加功能、修改功能,都需要使用以上套路进行登录校验。此时就会出现:相同代码逻辑,每个功能都需要编写,就会造成代码非常繁琐。

为了简化这块操作,我们可以使用一种技术:统一拦截技术。

  • 通过统一拦截的技术,我们可以来拦截浏览器发送过来的所有的请求,拦截到这个请求之后,就可以通过请求来获取之前所存入的登录标记,在获取到登录标记,且标记为登录成功,就说明员工已经登录了。如果已经登录,我们就直接放行(意思就是可以访问正常的业务接口了)。
  1. 在员工登录成功后,需要将用户登录成功的信息存起来,记录用户已经登录成功的标记。

  2. 在浏览器发起请求时,需要在服务端进行统一拦截,拦截后进行登录校验。

统一拦截技术

   

我们要完成以上登录校验的操作,会涉及到Web开发中的两个技术:

  1. 会话技术

  2. 统一拦截技术

    

 

 

异常处理的方案!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/929849.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【Go 基础篇】Go 语言字符串函数详解:处理字符串进阶

大家好!继续我们关于Go语言中字符串函数的探索。字符串是编程中常用的数据类型,而Go语言为我们提供了一系列实用的字符串函数,方便我们进行各种操作,如查找、截取、替换等。在上一篇博客的基础上,我们将继续介绍更多字…

登录认证-登录校验-会话技术

目录 会话技术 会话跟踪方案对比 方案一:Cookie 实现思路 具体代码 优点 缺点 方案二:Session 实现思路 具体代码 优点 缺点 方案三:令牌技术(主流方案) 实现思路 优点 缺点 会话技术 会话&#xff1a…

网络安全实验室搭建与实践:提供搭建虚拟实验环境的指导

随着数字化时代的来临,网络安全问题变得愈发严重和复杂。在这个信息交织的世界里,了解并掌握网络安全已经成为刻不容缓的任务。而搭建一个稳定、真实的网络安全实验环境,成为学习和实践的必然选择。本文将为您详细介绍网络安全实验室的搭建过…

一所南方学校,遇上AI的60天

AI大模型的想象力是什么? 有的人认为是参数,有的人可能回答是逻辑和推理,还有的人给出的选项是数据新式表达。 而这些答案,都需要在 一个个真实的产业场景里被实践,被验证。 对谢柏芳和东区中学而言,这个…

python+django+mysql旅游景点推荐系统-前后端分离(源码+文档)

系统主要采用Python开发技术和MySQL数据库开发技术以及基于OpenCV的图像识别。系统主要包括系统首页、个人中心、用户管理、景点信息管理、景点类型管理、景点门票管理、在线反馈、系统管理等功能,从而实现智能化的旅游景点推荐方式,提高旅游景点推荐的效…

4.6 TCP面向字节流

TCP 是面向字节流的协议,UDP 是面向报文的协议 操作系统对 TCP 和 UDP 协议的发送方的机制不同,也就是问题原因在发送方。 UDP面向报文协议: 操作系统不会对UDP协议传输的消息进行拆分,在组装好UDP头部后就交给网络层处理&…

clickhouse一次异常排查记录

clickhouse中报错 关闭了自启动,删了status,重启了clickhouse还是报错 1,排查定时执行的脚本日志(每小时第5分钟执行) INSERT INTO quality0529.previously_reported_urls (url) SELECT url FROM quality0529.hourly_…

基于Python的文件销毁工具设计与实现【源码+论文+演示视频+包运行成功】

博主介绍:✌csdn特邀作者、博客专家、java领域优质创作者、博客之星,擅长Java、微信小程序、Python、Android等技术,专注于Java、Python等技术领域和毕业项目实战✌ 🍅文末获取源码联系🍅 👇🏻…

系统架构设计高级技能 · 面向服务架构设计理论与实践

系列文章目录 系统架构设计高级技能 软件架构概念、架构风格、ABSD、架构复用、DSSA(一)【系统架构设计师】 系统架构设计高级技能 系统质量属性与架构评估(二)【系统架构设计师】 系统架构设计高级技能 软件可靠性分析与设计…

使用信号处理算法过滤加速度数据并将其转换为速度和位移研究(Matlab代码实现)

💥💥💞💞欢迎来到本博客❤️❤️💥💥 🏆博主优势:🌞🌞🌞博客内容尽量做到思维缜密,逻辑清晰,为了方便读者。 ⛳️座右铭&a…

2023谷歌开发者大会直播大纲「初稿」

听人劝、吃饱饭,奉劝各位小伙伴,不要订阅该文所属专栏。 作者:不渴望力量的哈士奇(哈哥),十余年工作经验, 跨域学习者,从事过全栈研发、产品经理等工作,现任研发部门 CTO 。荣誉:2022年度博客之星Top4、博客专家认证、全栈领域优质创作者、新星计划导师,“星荐官共赢计…

VS插件DevExpress CodeRush v23.1 - 支持Visual Studio ARM

DevExpress CodeRush是一个强大的Visual Studio .NET 插件,它利用整合技术,通过促进开发者和团队效率来提升开发者体验。CodeRush能帮助你以极高的效率创建和维护源代码。Consume-first 申明,强大的模板,智能的选择工具&#xff0…

2023MySQL+MyBatis知识点整理

文章目录 主键 外键 的区别?什么是范式?什么是反范式?什么是事务?MySQL事务隔离级别?MySQL事务默认提交模式?MySQL中int(1)和int(10)的区别MySQL 浮点数会丢失精度吗?MySQL支持哪几种时间类型&a…

Redis 7 教程 数据类型 基础篇

🌹 引导 Commands | Redishttps://redis.io/commands/Redis命令中心(Redis commands) -- Redis中国用户组(CRUG)Redis命令大全,显示全部已知的redis命令,redis集群相关命令,近期也会翻译过来,Redis命令参考,也可以直接输入命令进行命令检索。

【电路设计】单节锂电池使用

前言 最近在研究如何利用单节锂电池给3.3V单片机供电。 找到两个比较好的教程 单节锂电池如何转3.3V?升压还是降压? 锂电池接了保护板,就可以用五伏电压直接充电了吗? 其中上面提到的LDO,这里有一个型号&#xff1…

身为一个后端程序员如何快速制作后端管理系统的UI

前言 我的专业领域在后端开发上,前端我仅仅是熟悉,但是要从头开发一个前端UI界面有点难为人了。那么身为一个后端程序员我们怎么来开发后端管理系统UI界面呢? 方案1:现成的模版来套(有一定的前端基础,只是…

AI人工智能面试题

目录 01、监督学习和非监督学习? 02、常用的分类器有哪些,简述其原理? 03、逻辑回归(LR,Logistic Regression)与线性回归的对比 05、简述一下BP网络神经 06、AdaBoost的基本原理? 07、聚类算法——说一下你所熟悉的聚类的算…

数据隐私与安全在大数据时代的挑战与应对

文章目录 数据隐私的挑战数据安全的挑战应对策略和方法1. 合规和监管2. 加密技术3. 匿名化和脱敏4. 安全意识培训5. 隐私保护技术 结论 🎈个人主页:程序员 小侯 🎐CSDN新晋作者 🎉欢迎 👍点赞✍评论⭐收藏 ✨收录专栏&…

开源网安受邀参加软件供应链安全沙龙,推动企业提升安全治理能力

​8月23日下午,合肥软件行业软件供应链安全沙龙在中安创谷科技园举办。此次沙龙由合肥软件产业公共服务中心联合中安创谷科技园公司共同主办,开源网安软件供应链安全专家王晓龙、尹杰受邀参会并带来软件供应链安全方面的精彩内容分享,共同探讨…

certbot-https证书自动续期

certbot是一个免费的开源项目是EFF的一部分,自动化的工具,用于帮助管理和续期SSL/TLS证书。它可以安装、配置和自动续期证书。 1、安装 snapd 将 EPEL 存储库添加到您的 CentOS 安装中。输入y回车继续安装 sudo yum install snapd; sudo systemctl en…