登录校验及全局异常处理器

登录校验

会话技术
  • 会话:用户打开浏览器,访问web服务器的资源,会话建立,直到有一方断开连接,会话结束.在一次会话中可以包含多次请求和响应
  • 会话跟踪:一种维护浏览器状态的方法,服务器需要识别多次请求是否来自于同一浏览器,以便在同一次会话请求间共享数据
  • 会话跟踪方案
    1. 客户端会话跟踪技术:Cookie
    2. 服务端会话跟踪技术:Session
    3. 令牌技术
JWT令牌(JSON Web Token)
1. 组成
  • 第一部分:Heade(头),记录令牌类型,算法签名等。例如:{"alg":"HS256","type":"JWT"}
  • 第二部分:Payload(有效载荷),携带一些自定义信息,默认信息等等。例如:{"id":"1","name":"Tom"}
  • 第三部分:Signature(签名),防止Token被篡改,确保安全性。将Header , payload , 并加入指定秘钥 , 通过指定签名算法计算而来
2. 生成/解析
 @Test
    public void testGenJWT(){
        HashMap<String, Object> claims = new HashMap<>();
        claims.put("id",1);
        claims.put("name","Tom");

        String jwt = Jwts.builder()
                .signWith(SignatureAlgorithm.HS256, "comcrn")//签名算法
                .setClaims(claims)//自定义内容,载荷
                .setExpiration(new Date(System.currentTimeMillis() + 3600 * 1000))//设置有效期是一个小时
                .compact();

        System.out.println(jwt);
    }

@Test//解析
    public void testParseJwt(){
        Claims claims= Jwts.parser()
                .setSigningKey("comcrn")
                .parseClaimsJws("eyJhbGciOiJIUzI1NiJ9.eyJuYW1lIjoiVG9tIiwiaWQiOjEsImV4cCI6MTcxNjk5NTA1Nn0.ArBnzJo8SWv1YbJIddsiH8_ZgAX_IapDf0vENI43tfo")
                .getBody();
        System.out.println(claims);
    }
过滤器Filter
  • 一般完成一些通用的操作 , 比如 : 登录校验 , 统一编码处理 , 敏感字符处理等 .
1. 快速入门
1.1. 定义Filter:定义一个类,实现Filter接口,并重写其所有方法
package com.crn.filter;


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 {
        Filter.super.init(filterConfig);
    }

    @Override //拦截到请求之后调用,调用多次
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        //放行
        filterChain.doFilter(servletRequest,servletResponse);
    }

    @Override//销毁方法,只调用一次
    public void destroy() {
        Filter.super.destroy();

    }
}
1.2. 配置Filter:Filter配置类上加@WebFilter注解,配置资源拦截的路劲.引导类加上@ServletComponentScan开启支持Servlet组件
package com.crn;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.web.servlet.ServletComponentScan;

@ServletComponentScan
@SpringBootApplication
public class SpringbootTliasYbApplication {

    public static void main(String[] args) {
        SpringApplication.run(SpringbootTliasYbApplication.class, args);
    }

}

 <dependency>
            <groupId>io.jsonwebtoken</groupId>
            <artifactId>jjwt</artifactId>
            <version>0.9.1</version>
        </dependency>
2. 过滤器链
  • 注解配置的Filter,优先级是按照过滤器类名(字符串)的自然排序
3. 登录校验流程
package com.crn.filter;


import com.alibaba.fastjson.JSONObject;
import com.crn.pojo.Result;
import com.crn.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.getRequestURL().toString();
        log.info("url:{}", url);

        //2.判断URL中是否包含login,如果包含,说明是登录操作,放行
        if(url.contains("login")){
            log.info("登录操作,放行");
            filterChain.doFilter(servletRequest, servletResponse);
            return;
        }

        //3.获取请求头中的令牌
        String jwt = req.getHeader("token");

        //4.判断令牌是否存在
        if(!StringUtils.hasLength(jwt)){
            //令牌不存在,说明用户没有登录,返回错误信息
            log.info("令牌不存在,请先登录");
            Result error = Result.error("NOT_LOGIN");
            //手动转换  对象-->json  ---->阿里巴巴fastJSON
            String jsonString = JSONObject.toJSONString(error);
            resp.getWriter().write(jsonString);
            return ;
        }

        //5.解析token,如果解析失败,返回错误结果
        try {
            JwtUtils.parseJWT(jwt);
        } catch (Exception e) { //解析失败
            e.printStackTrace();
            log.info("令牌解析失败");
            Result error = Result.error("NOT_LOGIN");
            //手动转换  对象-->json  ---->阿里巴巴fastJSON
            String jsonString = JSONObject.toJSONString(error);
            resp.getWriter().write(jsonString);
            return ;
        }

        //6.放行
        log.info("令牌合法,放行");
        filterChain.doFilter(servletRequest, servletResponse);
    }
}
拦截器Interceptor
  • spring框架提供的,用来动态拦截控制器方法的执行
1. 快速入门
1.1. 定义拦截器,实现HandlerInterceptor接口,并从写其方法
package com.crn.interceptor;

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,代表放行;返回值为false,代表拦截
    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运行了...");
    }
}
1.2. 定义拦截器
package com.crn.config;

import com.crn.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. 登录校验流程
package com.crn.interceptor;

import com.alibaba.fastjson.JSONObject;
import com.crn.pojo.Result;
import com.crn.utils.JwtUtils;
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;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@Slf4j
@Component
public class LoginCheckInterceptor implements HandlerInterceptor {

    @Override //目标资源方法运行前运行,返回为true,代表放行;返回值为false,代表拦截
    public boolean preHandle(HttpServletRequest req, HttpServletResponse resp, Object handler) throws Exception {

        //1.获取请求url
        String url = req.getRequestURL().toString();
        log.info("url:{}", url);

        //2.判断URL中是否包含login,如果包含,说明是登录操作,放行
        if(url.contains("login")){
            log.info("登录操作,放行");
            return true;
        }

        //3.获取请求头中的令牌
        String jwt = req.getHeader("token");

        //4.判断令牌是否存在
        if(!StringUtils.hasLength(jwt)){
            //令牌不存在,说明用户没有登录,返回错误信息
            log.info("令牌不存在,请先登录");
            Result error = Result.error("NOT_LOGIN");
            //手动转换  对象-->json  ---->阿里巴巴fastJSON
            String jsonString = JSONObject.toJSONString(error);
            resp.getWriter().write(jsonString);
            return false;
        }

        //5.解析token,如果解析失败,返回错误结果
        try {
            JwtUtils.parseJWT(jwt);
        } catch (Exception e) { //解析失败
            e.printStackTrace();
            log.info("令牌解析失败");
            Result error = Result.error("NOT_LOGIN");
            //手动转换  对象-->json  ---->阿里巴巴fastJSON
            String jsonString = JSONObject.toJSONString(error);
            resp.getWriter().write(jsonString);
            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运行了...");
    }
}
过滤器与拦截器的区别
  • 接口规范不同:过滤器需要实现Filter接口,二拦截器需要实现HandleInterceptor接口
  • 拦截范围不同:过滤器Filer会拦截所有资源,而Interceptor只会拦截进入Spring环境中的资源

异常处理器

package com.crn.exception;

import com.crn.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 e){
        e.printStackTrace();
        return Result.error("对不起,操作失败,请联系管理员");
    }
}
相关推荐
山语山4 分钟前
C语言——文件读写操作
java·c语言·前端·microsoft·visual studio
芝法酱4 分钟前
芝法酱学习笔记(0.6)——nexus与maven私库
java·maven·nexus
u01040583610 分钟前
Java后端开发中的数据保护:如何实现全面的数据加密
java·开发语言
点点滴滴的记录31 分钟前
2017~2018博文汇总目录
java·大数据
夜月行者1 小时前
如何使用ssm实现民族大学创新学分管理系统分析与设计+vue
java·后端·ssm
艾伦~耶格尔1 小时前
IDEA 配置 Git 详解
java·ide·git·后端·intellij-idea
云兮杜康1 小时前
IDEA中用过git之后文件名颜色全变红
java·git·intellij-idea
customer081 小时前
【开源免费】基于SpringBoot+Vue.JS洗衣店订单管理系统(JAVA毕业设计)
java·vue.js·spring boot·后端·开源
杨荧1 小时前
【JAVA开源】基于Vue和SpringBoot的周边产品销售网站
java·开发语言·vue.js·spring boot·spring cloud·开源
橘橙黄又青1 小时前
多线程-初阶(1)
java·开发语言