登录认证,登录校验

news2024/11/19 10:21:34

一、基础登录功能

 1.Controller层

import com.itheima.pojo.Emp;
import com.itheima.pojo.Result;
import com.itheima.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.RestController;

@Slf4j
@RestController
public class LoginController {
    @Autowired
    private EmpService empService;

    @PostMapping("/login")
    public Result login(@RequestBody Emp emp){
        log.info ( "登录用户名:{},密码:{}",emp );
    Emp e =empService.login(emp);
        return e!=null?Result.success ():Result.error ( "用户名或密码错误" );

    }
}

2.Service层

    @Override
    public Emp login(Emp emp) {
        return empMapper.getByusernameAndPassword(emp);
    }
}

3.Mapper层

 /**
     * 根据用户名密码查询员工
     * @param emp
     * @return
     */

    @Select ( "select * from emp where username=#{username} and password=#{password}")
    Emp getByusernameAndPassword(Emp emp);

二、登录校验

1.会话技术

1.会话跟踪方案对比


import com.itheima.pojo.Result;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

/**
 * HttpSession演示
 */
@Slf4j
@RestController
public class SessionController {

    //设置Cookie
    @GetMapping("/c1")
    public Result cookie1(HttpServletResponse response){
        response.addCookie(new Cookie("login_username","itheima")); //设置Cookie/响应Cookie
        return Result.success();
    }

    //获取Cookie
    @GetMapping("/c2")
    public Result cookie2(HttpServletRequest request){
        Cookie[] cookies = request.getCookies();
        for (Cookie cookie : cookies) {
            if(cookie.getName().equals("login_username")){
                System.out.println("login_username: "+cookie.getValue()); //输出name为login_username的cookie
            }
        }
        return Result.success();
    }



    @GetMapping("/s1")
    public Result session1(HttpSession session){
        log.info("HttpSession-s1: {}", session.hashCode());

        session.setAttribute("loginUser", "tom"); //往session中存储数据
        return Result.success();
    }

    @GetMapping("/s2")
    public Result session2(HttpServletRequest request){
        HttpSession session = request.getSession();
        log.info("HttpSession-s2: {}", session.hashCode());

        Object loginUser = session.getAttribute("loginUser"); //从session中获取数据
        log.info("loginUser: {}", loginUser);
        return Result.success(loginUser);
    }
}

2.JWT令牌技术

/**
     * 测试Jwt令牌的生成
     */
    @Test
    public void testGenJwt(){
        Map<String, Object> claims=new HashMap<> ();
        claims.put ( "id",1 );
        claims.put ( "name","TOM" );
        String jwt = Jwts.builder ()
                .signWith ( SignatureAlgorithm.HS256, "itheima" )//签名算法
                .setClaims ( claims )//自定义内容(载荷)
                .setExpiration ( new Date ( System.currentTimeMillis ()  ) )
//                .setExpiration ( new Date ( System.currentTimeMillis () + 3600 * 1000 ) )//设置令牌的有效期为1个小时
                .compact ();//返回一个jwt令牌
        System.out.println (jwt);
    }

1.生成JWT令牌

2.令牌解析

    @Test
    public void testPrasejwt(){
        Claims claims = Jwts.parser ()
                .setSigningKey ( "itheima" )
                .parseClaimsJws ( "eyJhbGciOiJIUzI1NiJ9.eyJuYW1lIjoiVE9NIiwiaWQiOjEsImV4cCI6MTY5NzAwOTgwN30.9iduxbB4vpQLGs3anczG-spuQdT5f_3BR6aHYYHop3M" )
                .getBody ();
        System.out.println ( claims );
    }

3.登陆后下发令牌

1.jwtUtils类
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import java.util.Date;
import java.util.Map;

public class JwtUtils {

    private static String signKey = "itheima";
    private static Long expire = 43200000L;

    /**
     * 生成JWT令牌
     * @param claims JWT第二部分负载 payload 中存储的内容
     * @return
     */
    public static String generateJwt(Map<String, Object> claims){
        String jwt = Jwts.builder()
                .addClaims(claims)
                .signWith(SignatureAlgorithm.HS256, signKey)
                .setExpiration(new Date(System.currentTimeMillis() + expire))
                .compact();
        return jwt;
    }

    /**
     * 解析JWT令牌
     * @param jwt JWT令牌
     * @return JWT第二部分负载 payload 中存储的内容
     */
    public static Claims parseJWT(String jwt){
        Claims claims = Jwts.parser()
                .setSigningKey(signKey)
                .parseClaimsJws(jwt)
                .getBody();
        return claims;
    }
}
2.Controller层
import com.itheima.pojo.Emp;
import com.itheima.pojo.Result;
import com.itheima.service.EmpService;
import com.itheima.utils.JwtUtils;
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.RestController;

import java.util.HashMap;
import java.util.Map;

@Slf4j
@RestController
public class LoginController {
    @Autowired
    private EmpService empService;

    @PostMapping("/login")
    public Result login(@RequestBody Emp emp){
        log.info ( "登录用户名:{},密码:{}",emp );
    Emp e =empService.login(emp);
    //登陆成功,生成令牌,下发令牌
    if (e!=null){
        Map<String, Object> claims=new HashMap<> ();
        claims.put ( "id",e.getId () );
        claims.put ( "name",e.getUsername () );
        claims.put ( "username",e.getUsername () );
        String jwt = JwtUtils.generateJwt ( claims );//jwt 包含了当前登录的员工信息
        return Result.success (jwt);//下发jwt令牌
    }

    //登录失败,返回错误信息
        return Result.error ( "用户名或密码错误" );

    }
}

三、过滤器 -Filter

1.入门程序

import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import java.io.IOException;
@WebFilter(urlPatterns = "/*")
public class DemoFilter implements Filter {
    @Override //初始化方法只调用一次
    public void init(FilterConfig filterConfig) throws ServletException {
        System.out.println ("初始化方法被调用了");
    }

    @Override   //拦截到请求之后调用
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain chain) throws IOException, ServletException {
        System.out.println ("拦截到了请求");
        chain.doFilter ( servletRequest,servletResponse );//放行
    }

    @Override //销毁方法,只调用一次
    public void destroy() {
        System.out.println ("销毁方法被调用了");
    }
}

2.Filter详解

1.Filter执行流程

2.过滤器的拦截路径

3.过滤器链

3.Filter完成登录校验

1.LoginCheckFilter

import com.alibaba.fastjson.JSONObject;
import com.itheima.pojo.Result;
import com.itheima.utils.JwtUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.util.StringUtils;

import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

@Slf4j
@WebFilter(urlPatterns = "/*")
public class LoginCheckFilter implements Filter {
    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {

        HttpServletRequest req = (HttpServletRequest) servletRequest;
        HttpServletResponse resp = (HttpServletResponse) servletResponse;
    //1.获取请求url
        String url = req.getRequestURI ().toString ();
        log.info ( "请求的url:{}",url );
    //2.判断请求url中是否包含login,如果包含,说明是登陆操作,放行
        if (url.contains ( "login" )){
            log.info ("登陆操作,放行...");
            filterChain.doFilter (servletRequest,servletResponse  );
            return;
        }
    //3.获取请求头的令牌(token)
        String jwt = req.getHeader ( "token" );

    //4.判断令牌是否存在,如果不存在,返错误结果(未登录)
    if (!StringUtils.hasLength ( jwt )){
        log.info ( "请求头token为空,返回未登录的信息" );
        Result error = Result.error ( "NOT_LOGIN" );
        //手动转换Josn数据
        String notLogin = JSONObject.toJSONString ( error );
        resp.getWriter ().write ( notLogin );
        return;
    }
    //5.解析token,如果解析失败,返回错误结果(未登录)
        try {
            JwtUtils.parseJWT ( jwt );
        } catch (Exception e) {
            e.printStackTrace ();
            log.info ( "解析令牌失败,返回未登录错误信息" );
            Result error = Result.error ( "NOT_LOGIN" );
            //手动转换Josn数据
            String notLogin = JSONObject.toJSONString ( error );
            resp.getWriter ().write ( notLogin );
            return;
        }
        //6.放行
        log.info ( "令牌合法,放行" );
        filterChain.doFilter ( servletRequest,servletResponse );
    }
}

2.手动将字符串转换为JSON格式数据

 //手动转换Josn数据
        String notLogin = JSONObject.toJSONString ( error );
        resp.getWriter ().write ( notLogin );

3.引入依赖

        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>fastjson</artifactId>
            <version>2.0.32</version>
        </dependency>

四、拦截器

1.拦截器的基本使用

1.定义拦截器

import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@Component
public class LoginCheckInterceptor implements HandlerInterceptor {
    @Override//目标资源方法运行前运行,返回true 放行
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        System.out.println ("preHandle...");
        return true;
    }

    @Override//目标资源方法运行后运行
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        System.out.println ("postHandle.....");
    }

    @Override//视图渲染完毕后,最后运行
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        System.out.println ("afterCompletion...");
    }
}

2.配置拦截器

import com.itheima.interceptor.LoginCheckInterceptor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Configuration//配置类
public class WebConfig implements WebMvcConfigurer {
    @Autowired
    private LoginCheckInterceptor loginCheckInterceptor;
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor ( loginCheckInterceptor ).addPathPatterns ( "/**" );
    }
}

2.拦截路径,执行流程

 3.拦截器完成登录校验

import com.alibaba.fastjson.JSONObject;
import com.itheima.pojo.Result;
import com.itheima.utils.JwtUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.util.StringUtils;

import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

@Slf4j
//@WebFilter(urlPatterns = "/*")
public class LoginCheckFilter implements Filter {
    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {

        HttpServletRequest req = (HttpServletRequest) servletRequest;
        HttpServletResponse resp = (HttpServletResponse) servletResponse;
    //1.获取请求url
        String url = req.getRequestURI ().toString ();
        log.info ( "请求的url:{}",url );
    //2.判断请求url中是否包含login,如果包含,说明是登陆操作,放行
        if (url.contains ( "login" )){
            log.info ("登陆操作,放行...");
            filterChain.doFilter (servletRequest,servletResponse  );
            return;
        }
    //3.获取请求头的令牌(token)
        String jwt = req.getHeader ( "token" );

    //4.判断令牌是否存在,如果不存在,返错误结果(未登录)
    if (!StringUtils.hasLength ( jwt )){
        log.info ( "请求头token为空,返回未登录的信息" );
        Result error = Result.error ( "NOT_LOGIN" );
        //手动转换Josn数据
        String notLogin = JSONObject.toJSONString ( error );
        resp.getWriter ().write ( notLogin );
        return;
    }
    //5.解析token,如果解析失败,返回错误结果(未登录)
        try {
            JwtUtils.parseJWT ( jwt );
        } catch (Exception e) {
            e.printStackTrace ();
            log.info ( "解析令牌失败,返回未登录错误信息" );
            Result error = Result.error ( "NOT_LOGIN" );
            //手动转换Josn数据
            String notLogin = JSONObject.toJSONString ( error );
            resp.getWriter ().write ( notLogin );
            return;
        }
        //6.放行
        log.info ( "令牌合法,放行" );
        filterChain.doFilter ( servletRequest,servletResponse );
    }
}

五、异常处理

import com.itheima.pojo.Result;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;

/**
 * 全局异常处理器
 */
@RestControllerAdvice
public class GlobalExceptionHandler {
    @ExceptionHandler(Exception.class)//捕获异常的类型
 public Result ex(Exception exception){
        return Result.error ( "对不起操作失败,请联系管理员" );
    }
}

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

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

相关文章

ChatGLM2-6B微调实践-QLora方案

ChatGLM2-6B微调实践-QLora方案 环境部署Lora微调项目部署准备数据集修改训练脚本adapter推理模型合并与量化合并后的模型推理 参数调优微调过程中遇到的问题参考&#xff1a; 环境部署 申请阿里云GPU服务器&#xff1a; CentOS 7.6 64Anaconda3-2023.07-1-Linux-x86_64Pytho…

为什么力扣中std::sort的cmp函数不加static会出错?

今天在力扣上做题的时候出现了一个有意思的错误 题目&#xff1a;1005.K 次取反后最大化的数组和 错误信息&#xff1a;error: reference to non-static member function must be called sort(nums.begin(),nums.end(),cmp); 我自定义了sort的cmp函数&#xff0c;但是出错了…

计算时间复杂度

时间复杂度与语句被重复执行的次数息息相关。 一、单层循环 单层循环大致可以分为两种&#xff0c;一种是循环体内的语句不影响循环条件的判定。另一种就是循环体内的语句会影响循环条件的判定。 1、循环体内的语句不影响循环条件的判定 这种情况十分常见且简单&#xff0c…

Configuration Change派发到App进程

整体时序 // DisplayContent.java boolean updateDisplayOverrideConfigurationLocked(Configuration values,ActivityRecord starting, boolean deferResume,ActivityTaskManagerService.UpdateConfigurationResult result) {int changes 0;boolean kept true;mAtmService.d…

VUEX全网最详细讲解之一

目录 一.Vuex简介 二.vuex的存值取值 测试结果 三.vuex异步请求 测试结果 ​编辑 ​编辑 一.Vuex简介 Vuex 是一个用于 Vue.js 应用程序的状态管理模式和库。它以集中式存储管理应用的所有组件的状态&#xff0c;并提供可预测的状态变化。Vuex 主要解决了多个组件之间共享…

Springboot——集成jodconverter做文档转换

文章目录 前言jodconverter 简介下载安装 libreoffice代码演示1、创建springboot项目工程并引入依赖2、配置3、准备一个docx模板4、编写测试代码 运行后的样式linux 环境下安装 libreoffice 前言 公司项目开发中&#xff0c;早期使用docx4j进行word转pdf&#xff0c;出现了很多…

嵌入式养成计划-39----C++静态成员--继承--多继承

九十一、静态成员 静态成员变量是属于类的变量&#xff0c;而不是属于类的对象的。它们在类的所有实例中是共享的。它们具有类范围的生命周期&#xff0c;因此与全局变量有一些相似之处。 在数据成员前static ----->静态数据成员 在成员函数前static ------>静态成员函…

接口自动化测试 —— 工具、请求与响应

1.工具介绍 postman &#xff1a;很主流的API测试工具&#xff0c;也是工作里面使用最广泛的研发工具。 JMeter&#xff1a; ApiPost&#xff1a; 2.安装postman&#xff1a; 安装好直接打开&#xff0c;不用注册。 二、通信模式&#xff1a; 1、同步通信&#xff1a; …

【走方格的方案数】

目录 一、题目描述二、算法原理三、代码实现 一、题目描述 二、算法原理 三、代码实现 #include <iostream> using namespace std; int func(int m,int n) {if(m1||n1){return mn;}return func(m-1,n)func(m,n-1); } int main() {int m, n;while (cin >>m >>…

word行距怎么设置?专业排版,让文档更具吸引力!

Microsoft Word是最常用的文字处理工具之一&#xff0c;广泛用于学术写作、商务沟通和文档编辑。掌握Word的基本功能是高效使用它的关键。本文将介绍word行距怎么设置的3种方法&#xff0c;以确保您的文档格式清晰、易读&#xff0c;让您的文档更具吸引力&#xff01; 方法1&am…

C++ 命名空间-----namespace(超详细解析,小白必看系列)

目录 一、前言 &#x1f34e;什么是C 二、关键字 三、命名空间&#xff08;重点&#xff09; &#x1f350;C语言--命名冲突 &#x1f349;C--命名空间的定义 &#x1f353;C--命名空间的使用 四、C输入&输出 五、共勉 一、前言 既博主学过C语言后又一新的语言&a…

动手学强化学习第2章多臂老虎机

2.1简介 多臂老虎机问题可以被看作简化版的强化学习问题。但是其只有动作和奖励没有状态信息&#xff0c;算是简化版的强化学习问题。 2.2问题介绍 2.2.1问题定义 在多臂老虎机(MAB)问题中&#xff0c;有一个有K根拉杆的老虎机&#xff0c;拉动每一根拉杆都对应一个关于奖励…

简单使用 Hugo 博客

之前用过 hugo&#xff0c;本次来分享一波&#xff0c;确实简单好用&#xff0c;可以持续使用&#xff0c;尤其是喜欢 GO语言的同学 hugo Hugo是一个用 Go语言 编写的静态网站生成器&#xff0c;可以快速地生成高效、安全和易于管理的静态网站。Hugo具有速度快、可定制性强、…

Linux引导故障排除:从问题到解决方案的详细指南

1 BIOS初始化 通电->对硬件检测->初始化硬件时钟 2 磁盘引导及其修复 2.1 磁盘引导故障 磁盘主引导记录&#xff08;MBR&#xff09;是在0磁道1扇区位置&#xff0c;446字节。 MBR作用&#xff1a;记录grub2引导文件的位置 2.2 修复 步骤&#xff1a;1、光盘进…

Javascript笔记:Web页面中的事件处理

1 任务队列 2事件处理&#xff1a;⼀个只有宏任务的示例 3 Web⻚⾯中的事件处理 3.1 定时器与事件处理&#xff1a;一个实例 4 Web⻚⾯中的事件处理 5 事件在DOM中的传播 5.1 两个阶段

C++ (Chapter 1)

C (一) 1.C的命名空间 先来看一个C语言的例子: 下面这段代码是可以正常运行的. #include<stdio.h> int rand 0; int main() {printf("%d \n", rand);return 0; }但是,包含了一个头文件之后,甚至无法通过编译. #include<stdio.h> #include<stdli…

尘封已久的功能!iPhone 15带来了一项早该使用的电池功能

了解如何在iPhone 15上检查电池周期&#xff0c;在设备使用寿命的某个阶段将非常有用。只要简单地看一眼完成的循环次数&#xff0c;你就可以确定你的电池有多健康&#xff0c;以及你是否需要很快更换它。 这是iPhone在过去一直缺失的东西。iPhone上有检查电池周期的数据&…

Altium Designer实用系列(三)----部分问题解决办法(连完所有的线之后还存在飞线,isolated copper...)

一、常见问题解决 1.1 连完所有的线之后还存在飞线 出现此问题可以尝试把该PCB先关闭&#xff0c;然后关闭Altium Designer软件。之后再打开Altium Designer&#xff0c;之后再进行DRC电气检查&#xff0c;可解决该问题。 1.2 isolated copper:split plane(xxx)on … 该问题…

计算机毕业设计选什么题目好?springboot智慧养老中心管理系统

✍✍计算机编程指导师 ⭐⭐个人介绍&#xff1a;自己非常喜欢研究技术问题&#xff01;专业做Java、Python、微信小程序、安卓、大数据、爬虫、Golang、大屏等实战项目。 ⛽⛽实战项目&#xff1a;有源码或者技术上的问题欢迎在评论区一起讨论交流&#xff01; ⚡⚡ Java实战 |…

C++入门篇1

文章目录 C入门篇11、命名空间1.1、命名空间定义1.2、命名空间的使用 2、输入&输出3、缺省参数3.1、缺省参数概念3.2、缺省参数分类 C入门篇1 1、命名空间 1.1、命名空间定义 命名空间是什么&#xff1f;是一种将相关功能和数据封装在一起的方式&#xff0c;以避免名称冲…