Javaweb-day12(登录认证)

登录功能

登录校验(重点)

登录校验指的是在服务器接收到浏览器发送过来的请求之后,首先要对这个请求进行校验,先要校验一下用户登录了没有

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

  1. 在员工登录成功后,需要将用户登录成功的信息存起来,记录用户已经登录成功的标记。

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

会话技术

会话跟踪技术:

Cookie(客户端会话跟踪技术)

数据存储在客户端浏览器当中

服务器端在给客户端在响应数据的时候,会自动 的将 cookie 响应给浏览器,浏览器接收到响应回来的 cookie 之后,会自动 的将 cookie 的值存储在浏览器本地。接下来在后续的每一次请求当中,都会将浏览器本地所存储的 cookie 自动地携带到服务端。

Session(服务端会话跟踪技术)

数据存储在储在服务端

底层就是基于cookie实现的

令牌技术

令牌就是一个用户身份的标识,本质就是一个字符串

如果通过令牌技术来跟踪会话,我们就可以在浏览器发起请求。在请求登录接口的时候,如果登录成功,我就可以生成一个令牌,令牌就是用户的合法身份凭证。接下来我在响应数据的时候,我就可以直接将令牌响应给前端。

接下来我们在前端程序当中接收到令牌之后,就需要将这个令牌存储起来。这个存储可以存储在 cookie 当中,也可以存储在其他的存储空间(比如:localStorage)当中。

接下来,在后续的每一次请求当中,都需要将令牌携带到服务端。携带到服务端之后,接下来我们就需要来校验令牌的有效性。如果令牌是有效的,就说明用户已经执行了登录操作,如果令牌是无效的,就说明用户之前并未执行登录操作。

此时,如果是在同一次会话的多次请求之间,我们想共享数据,我们就可以将共享的数据存储在令牌当中就可以了。

JWT令牌

简洁:是指jwt就是一个简单的字符串。可以在请求参数或者是请求头当中直接传递。

自包含:指的是jwt令牌,看似是一个随机的字符串,但是我们是可以根据自身的需求在jwt令牌中存储自定义的数据内容。如:可以直接在jwt令牌中存储用户的相关信息。

简单来讲,jwt就是将原始的json数据格式进行了安全的封装,这样就可以直接基于jwt在通信双方安全的进行信息传输了。

java 复制代码
//   生成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,"wujiaowujiao")//签名算法
                .setClaims(claims)//自定义内容(载荷)
                .setExpiration(new Date(System.currentTimeMillis()+3600*1000))//设置有效期为1h
                .compact();
        System.out.println(jwt);
    }
//    解析JWT
    @Test
    public void testParseJWT(){
        Claims claims = Jwts.parser()
                .setSigningKey("wujiaowujiao")//指定签名密钥
                .parseClaimsJws("eyJhbGciOiJIUzI1NiJ9.eyJuYW1lIjoidG9tIiwiaWQiOjEsImV4cCI6MTczMTc0MDk2MH0.XNxy4S4R9U_PyYf17xNeHLHIaFIFmB3fSQW7xwCm2SM")//解析令牌
                .getBody();
        System.out.println(claims);
    }

过滤器Filter

快速入门

filter是Javaweb三大组件之一,并不是springboot当中提供的功能,在springboot项目中,要想使用javaweb的三大组件,必须在启动类上面加上一个注解@ServletComponentScan

详解
执行流程

过滤器拦截到了请求之后,首先先执行放行之前的逻辑,放行之前的逻辑执行完毕之后,执行放行操作,放行就是调用 FilterChain对象当中的doFilter()方法,在调用doFilter()这个方法之前所编写的代码属于放行之前的逻辑。

在放行后访问完 web 资源之后还会回到过滤器当中,回到过滤器之后如有需求还可以执行放行之后的逻辑,放行之后的逻辑我们写在doFilter()这行代码之后。

拦截路径
过滤器链

过滤器链指的是在一个web应用程序当中,可以配置多个过滤器,多个过滤器就形成了一个过滤器链。

通过控制台日志的输出,大家发现AbcFilter先执行DemoFilter后执行,这是为什么呢?

其实是和过滤器的类名有关系。以注解方式配置的Filter过滤器,它的执行优先级是按时过滤器类名的自动排序确定的,类名排名越靠前,优先级越高。

登录校验-Filter

因为tomcat传入的request实际上是HTTPrequest 这里是多态的思想

看一下源码就可以了,这里传递的是父类接口,这样子接口就可以完美兼容父接口

不懂不懂为什么

在tomcat那一章节,tomcat会将解析后的请求信息封装到一个对象中,这个对象就是httpservletrequest,我有这个印象

测试这块没跟,之后可以再看一下。

拦截器Interceptor

简介&快速入门

在拦截器当中,我们通常也是做一些通用性的操作,比如:我们可以通过拦截器来拦截前端发起的请求,将登录校验的逻辑全部编写在拦截器当中。在校验的过程当中,如发现用户登录了(携带JWT令牌且是合法令牌),就可以直接放行,去访问spring当中的资源。如果校验时发现并没有登录或是非法令牌,就可以直接给前端响应未登录的错误信息。

下面我们通过快速入门程序,来学习下拦截器的基本使用。拦截器的使用步骤和过滤器类似,也分为两步:

  1. 定义拦截器

  2. 注册配置拦截器

详解
拦截路径
执行流程

tomcat服务器不识别所编写的control程序,但是它识别servlet程序,因为tomcat是一个servlet容器,在springweb环境中,提供了一个非常核心的servlet,叫做前端控制器(DispatcherServlet)

  • 当我们打开浏览器来访问部署在web服务器当中的web应用时,此时我们所定义的过滤器会拦截到这次请求。拦截到这次请求之后,它会先执行放行前的逻辑,然后再执行放行操作。而由于我们当前是基于springboot开发的,所以放行之后是进入到了spring的环境当中,也就是要来访问我们所定义的controller当中的接口方法。

  • Tomcat并不识别所编写的Controller程序,但是它识别Servlet程序,所以在Spring的Web环境中提供了一个非常核心的Servlet:DispatcherServlet(前端控制器),所有请求都会先进行到DispatcherServlet,再将请求转给Controller。

  • 当我们定义了拦截器后,会在执行Controller的方法之前,请求被拦截器拦截住。执行preHandle()方法,这个方法执行完成后需要返回一个布尔类型的值,如果返回true,就表示放行本次操作,才会继续访问controller中的方法;如果返回false,则不会放行(controller中的方法也不会执行)。

  • 在controller当中的方法执行完毕之后,再回过来执行postHandle()这个方法以及afterCompletion() 方法,然后再返回给DispatcherServlet,最终再来执行过滤器当中放行后的这一部分逻辑的逻辑。执行完毕之后,最终给浏览器响应数据。

登录校验

登录校验的过滤器和拦截器,我们只需要使用其中的一种就可以了。

这次测试跟了。

java 复制代码
package com.wujiao.interceptor;

import com.alibaba.fastjson.JSONObject;
import com.wujiao.pojo.Result;
import com.wujiao.utils.JwtUtils;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

@Component
@Slf4j
public class LoginCheckInterceptor implements HandlerInterceptor {

    @Override//目标资源方法运行前运行,即controller方法,返回true;放行,返回false,不放行
    public boolean preHandle(HttpServletRequest req, HttpServletResponse res, Object handler) throws Exception {
        System.out.println("preHandle...");

//        1. 获取请求url
        String url = req.getRequestURL().toString();
        log.info("请求的url:{}",url);
//        2. 判断请求url中是否包含login,如果包含,说明是登录操作,放行
        if(url.contains("login")){
            log.info("登录操作,放行...");
            return true;
        }
//        3. 获取请求头中的令牌(token)
        String jwt = req.getHeader("token");
        log.info("从请求头中获取的令牌:{}",jwt);

//        4. 判断令牌是否存在,如果不存在,返回错误结果(未登录)
        if(!StringUtils.hasLength(jwt)){
            log.info("请求头token为空,返回未登录的信息");
            Result error = Result.error("NOT_LOGIN");
            String notLogin = JSONObject.toJSONString(error);//把Result对象转换为JSON格式字符串 (fastjson是阿里巴巴提供的用于实现对象和json的转换工具类)
            res.getWriter().write(notLogin);
            return false;

        }
//        5. 解析token,如果解析失败,返回错误结果(未登录)
        try {
            JwtUtils.parseJWT(jwt);
        } catch (Exception e) {//jwt解析失败

            log.info("解析令牌失败,返回未登录错误信息");
            Result error = Result.error("NOT_LOGIN");
            String notLogin = JSONObject.toJSONString(error);//把Result对象转换为JSON格式字符串 (fastjson是阿里巴巴提供的用于实现对象和json的转换工具类)
            res.getWriter().write(notLogin);
            return false;
        }
//        6. 放行
        log.info("令牌合法,放行");
        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...");
    }
}

异常处理

程序开发过程中不可避免的会遇到异常现象

出现异常时,默认返回的结果不符合规范,即返回的不是json格式的数据

以上就是全局异常处理器的使用,主要涉及到两个注解:

  • @RestControllerAdvice //表示当前类为全局异常处理器

  • @ExceptionHandler //指定可以捕获哪种类型的异常进行处理

java 复制代码
package com.wujiao.exception;

import com.wujiao.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 ex){
        ex.printStackTrace();
        return Result.error("对不起,操作失败,请联系管理员");
    }

}

及时复习呀

相关推荐
To_OC2 小时前
别再串行写 await 了,Promise.all 才是并行请求的正确打开方式
前端·javascript·promise
vipbic3 小时前
中后台越做越乱后,我用插件化把它救回来了
前端·vue.js
Hyyy3 小时前
Computer Use 适合做什么,不适合做什么——一次真实使用后的思考
前端
小和尚同志3 小时前
前端 AI 单元测试思考与落地
前端·人工智能·aigc
invicinble4 小时前
c端系统,其实更像一个信息展示平台
前端
李姆斯5 小时前
管理是否可以被完全量化
前端·产品经理·团队管理
weixin_307779136 小时前
Linux下Nginx故障系统化检查Shell脚本
linux·运维·服务器·nginx·自动化
名字还没想好☜6 小时前
Next.js 中间件实战:鉴权、重定向与 A/B 分流
开发语言·前端·javascript·中间件·react·next.js
广州灵眸科技有限公司6 小时前
瑞芯微RV1126B开发板(EASY-EAI-PI2) INI文件操作
java·前端·javascript·网络·人工智能
江华森7 小时前
Web 开发基础:HTTP 与 REST
前端·网络协议·http