使用Java登录校验

15 篇文章 0 订阅
13 篇文章 0 订阅

会话技术

        会话:用户打开浏览器,访问web服务器的资源,会话建立,直到有一方断开连接,会话结束。在一次会话可以包含多次请求和响应。

        会话跟踪:一种维护浏览器状态的方法,服务器需要识别多次请求是否来自同一浏览器,以便在同一次会话的多次请求间共享数据。

        会话跟踪方案:

                客户端会话跟踪技术:Cookie

                服务端会话跟踪技术:Session

                令牌技术

会话跟踪方案对比:

        Cookie-优点:HTTP协议中支持的技术

缺点:移动端APP无法使用Cookie

          不安全,用户可以自己禁用Cookie

          Cookie不能跨域

        Session-优点:存储在服务端,安全

        缺点:服务器集群环境下无法直接使用Session

                   Cookie的缺点

        优点:支持PC端、移动端

                   解决集群环境下的认证问题

                   减轻服务器端存储压力

           缺点:需要自己实现

JWT令牌

        全称:JSON Web Token

        定义了一种简洁的、自包含的格式,用于在通信双方以json数据格式安全的传输信息。由于数字签名的存在,这些信息是可靠的。

        组成:

                第一部分:Header(头),记录令牌类型,签名算法等。

                                例如:{"alg":"HS256","type":"JWT"}

                第二部分:Payload(有效载荷),携带一些自定义信息、默认信息等。

                                例如:{"id":"1","usename":"Tom"}

                第三部分:Signature(签名),防止Token被篡改、确保安全性。

                                将header、payload,并加入指定密钥,通过指定签名算法计算而来

JWT

        场景:登录认证

                1.登录成功后,生成令牌

                2.后续每个请求,都要携带JWT令牌,系统在每次请求处理之前,先校验令牌,同过后,再处理。

向pom.xml引入依赖:

 <dependency>
            <groupId>io.jsonwebtoken</groupId>
            <artifactId>jjwt</artifactId>
            <version>0.9.1</version>
        </dependency>
    @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, "itbignyi")
                .setClaims(claims)
                .setExpiration(new Date(System.currentTimeMillis() + 3600 * 1000))
                .compact();
        System.out.println(jwt);
@Test
    public void testParseJwt() {
        Claims claims = Jwts.parser()
                .setSigningKey("itbignyi")
                .parseClaimsJws("eyJhbGciOiJIUzI1NiJ9.eyJuYW1lIjoidG9tIiwiaWQiOjEsImV4cCI6MTY5NDUzMjAwOH0.D4TjgQSvqZJlUNioEKxUn8euvxu9gqnSo4jfsJGuL7Q")
                .getBody();
        System.out.println(claims);

注意事项:JWT校验时使用的签名密钥,必须和生成JWT令牌时使用的密钥时匹配的。

                如果JWT令牌解析校验时报错,则说明JWT令牌被篡改或者失效了,令牌非法

将代码写入:

过滤器Filter

概念:Filter过滤器,是JavaWeb三大组件(Servlet、Filter、Listener)之一

过滤器可以把对资源的请求拦截下来,从而实现一些特殊的功能

过滤器一般完成一些通用的操作,比如:登录校验、统一编码处理、处理敏感字符等。

定义Filter:定义一个类,实现Filter接口,并重写其所有方法

配置Filter:Filter类上加@WebFilter注解,配置拦截资源的路径,引导类上加@ServletComponerntScan开启Servlet组件支持。

package com.itheima.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();
    }
}

 Filter拦截路径:

        Filter可以根据需求,配置不同的拦截资源路径:

过滤器链:

        介绍:一个Web应用中,可以配置多个过滤器,这多个过滤器就形成了一个过滤器链

        顺序:注解配置的Filter,优先级是按照过滤器类名(字符串)的自然排序

 登录校验

        登录校验Filter-流程:

 1.获取请求url
 2.判断请求url中是否包含login,如果包含,说明登录操作,放行
 3.获取请求头中的令牌(token)
 4.判断令牌是否存在,如果不存在,返回错误结果(未登录)
 5.解析token,如果解析失败,返回错误结果(未登录)
 6.放行

package com.itheima.filter;

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.imageio.spi.ServiceRegistry;
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 res = (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");
            String notLogin = JSONObject.toJSONString(error);
            res.getWriter().write(notLogin);
            return;
        }
//         5.解析token,如果解析失败,返回错误结果(未登录)
        try {
            JwtUtils.pareJWT(jwt);
        } catch (Exception e) {
            e.printStackTrace();
            log.info("解析失败");
            Result error = Result.error("NOT_LOGIN");
            String notLogin = JSONObject.toJSONString(error);
            res.getWriter().write(notLogin);
            return;
        }
//         6.放行
        log.info("合法放行");
        filterChain.doFilter(servletRequest, servletResponse);


    }
}

拦截器Interceptor

概述:是一种动态拦截方法调用的机制,类似于过滤器。Spring框架中提供的,用来动态拦截控制器方法的执行

作用:拦截请求,在指定的方法调用前后,根据业务需要执行预先设定的代码

Interceptor快速入门

1.定义拦截器,实现HandlerInterceptor接口,并重写其所有方法

2.注册拦截器

package com.itheima.config;

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("/**");

    }

}
package com.itheima.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
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        return HandlerInterceptor.super.preHandle(request, response, handler);
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        HandlerInterceptor.super.postHandle(request, response, handler, modelAndView);
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        HandlerInterceptor.super.afterCompletion(request, response, handler, ex);
    }
}

拦截器-拦截路径

        拦截器可以根据需求,配置不同的拦截路径

拦截器-执行流程

 Filter和Interceptor

接口范围不同:过滤器需要实现Filter接口,而拦截器需要实现HandlerInterceptor接口

拦截范围不同:过滤器Filter会拦截所有资源,而Interceptor只会拦截Spring环境中的资源 

 运行代码:

package com.itheima.interceptor;

import com.alibaba.fastjson.JSONObject;
import com.itheima.pojo.Result;
import com.itheima.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
    public boolean preHandle(HttpServletRequest req, HttpServletResponse res, Object handler) throws Exception {


//         1.获取请求url
        String url = req.getRequestURI().toString();
        log.info("请求的url:{}", url);
//         2.判断请求url中是否包含login,如果包含,说明登录操作,放行
        if (url.contains("login")) {
            log.info("登录操作,放行...");
            return true;
        }
//         3.获取请求头中的令牌(token)
        String jwt = req.getHeader("token");
//         4.判断令牌是否存在,如果不存在,返回错误结果(未登录)
        if (!StringUtils.hasLength(jwt)) {
            log.info("请求头token,为空,返回未登录的信息");
            Result error = Result.error("NOT_LOGIN");
            String notLogin = JSONObject.toJSONString(error);
            res.getWriter().write(notLogin);
            return false;
        }
//         5.解析token,如果解析失败,返回错误结果(未登录)
        try {
            JwtUtils.pareJWT(jwt);
        } catch (Exception e) {
            e.printStackTrace();
            log.info("解析失败");
            Result error = Result.error("NOT_LOGIN");
            String notLogin = JSONObject.toJSONString(error);
            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 {
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
    }
}

异常处理

全局异常处理器

package com.itheima.exception;

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

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

冰逸.itbignyi

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值