SpringbootWeb登录认证

登录校验

会话技术

  • 会话:用户打开浏览器,访问web服务器的资源,会建立会话,直到有一方断开连接,会话结束。在一次会话中可以包含多次请求和响应。
  • 会话跟踪:一种维护浏览器状态的方法,服务器需要识别多次请求是否来自同一浏览器,以便在同一次会话的多次请求间共享数据。
会话跟踪技术
  • 客户端会话跟踪技术 :cookie

  • 服务器会话跟踪技术:session

  • 令牌技术

    腾讯云HTTP文档
    Cookie: HTTP 请求报头包含存储先前通过与所述服务器发送的 HTTP cookies Set-Cookie头。
    Set-Cookie: HTTP 响应报头被用于从服务器向用户代理发送 cookie。
    在这里插入图片描述
    cookie基本操作

@RestController
@Slf4j
public class SessionController {

   //设置cookie
   @GetMapping("/c1")
   public Result cookie1(HttpServletResponse response){
       response.addCookie(new Cookie("admin","123456"));
       return Result.success();
   }

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

在这里插入图片描述

在这里插入图片描述
cookie优缺点

  • 优点 :HTTP协议中支持的技术
  • 缺点 :移动APP无法使用cookie,不安全,用户可以自己禁用cookie,cookie不能跨域

Session
在这里插入图片描述

  @GetMapping("/s1")
    public Result session1(HttpSession session){
        session.setAttribute("admin","123456");
        return Result.success();
    }

    @GetMapping("/s2")
    public Result session2(HttpServletRequest request){
        HttpSession session = request.getSession();
        Object admin = session.getAttribute("admin");
        log.info("value:{}",admin);
        return Result.success();
    }

在这里插入图片描述
在这里插入图片描述

  • 优点:存储在服务端,安全。
  • 缺点: 服务器集群环境无法直接使用、 cookie的缺点

令牌
在这里插入图片描述

  • 优点:支持PC端、移动端。解决集群环境下的认证问题,减轻服务器存储压力。
  • 缺点: 需要自己实现。
JWT令牌

在这里插入图片描述

	<dependency>
           <groupId>io.jsonwebtoken</groupId>
           <artifactId>jjwt</artifactId>
           <version>0.9.1</version>
       </dependency>
Map<String, Object> claims =new HashMap<>();
        claims.put("id",1);
        claims.put("name","朱元璋");
        Jwts.builder()
                .signWith(SignatureAlgorithm.HS256,"admin")//签名算法
                .setClaims(claims)//自定义内容
                .setExpiration(new Date(System.currentTimeMillis()+60*60*1000))//设置有效期1h
                .compact();

//解析
  Map<String, Object> claims = Jwts.parser()
                .setSigningKey("admin")
                .parseClaimsJws("eyJhbGciOiJIUzI1NiJ9.eyJuYW1lIjoi5pyx5YWD55KLIiwiaWQiOjEsImV4cCI6MTcwMTY2MzM1Nn0.4dJvYxwjDYf_IP42cXDad967XZO3qV-EzPJbh8-aIzg")
                .getBody();
        System.out.println(claims);

JWT登录

  @Autowired
    private EmpService empService;
    @PostMapping("/login")
    public Result login(@RequestBody  Emp emp){
        Emp emp1 = empService.login(emp);
        //登录成功
        if(emp1 != null){
            Map<String, Object> claims = new HashMap<>();
            claims.put("id",emp1.getId());
            claims.put("username",emp1.getUsername());
            String jwt = JwtUtils.generateJwt(claims);
            return Result.success(jwt);
        }
        return Result.error("错误");
    }

JwtUtils.java


public class JwtUtils {
    private static String signKey = "admin";
    private static Long expire = 43200000L;
    public static String generateJwt(Map<String,Object> claims){
        String jwt = Jwts.builder()
                .signWith(SignatureAlgorithm.HS256,signKey )//签名算法
                .setClaims(claims)//自定义内容
                .setExpiration(new Date(System.currentTimeMillis() + expire))//设置有效期1h
                .compact();
        return jwt;
    }

    public static Claims parseJwt(String jwt){
        Claims claims = Jwts.parser()
                .setSigningKey(signKey)
                .parseClaimsJws(jwt)
                .getBody();
        return claims;
    }
}
过滤器 Filter

在这里插入图片描述

Filter快速入门

1.定义Filter类,实现filter接口
2.类上加上@WebFilter注解,配置拦截资源的路径。引导类加@ServletComponentScan开启servlet组件支持
在这里插入图片描述

//放行
filterChain.doFilter(servletRequest,servletResponse);
//放行之后的逻辑

放行之后会回到doFilter中,执行放行之后的逻辑。

过滤器链

在这里插入图片描述

登录校验Filter-流程

在这里插入图片描述

@WebFilter("/*")
@Slf4j
import com.alibaba.fastjson.JSONObject;
import com.example.demo.pojo.Result;
import com.example.demo.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;
public class LoginCheckFilter implements Filter {
    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        HttpServletRequest request = (HttpServletRequest) servletRequest;
        HttpServletResponse response = (HttpServletResponse) servletResponse;

        //1.获取请求url
        String url = request.getRequestURL().toString();
        //2.判断请求url是否包含login,如果包含,说明是登录操作,放行
        if(url.contains("login")){
            filterChain.doFilter(servletRequest,servletResponse);
            return;
        }
        //3.获取请求头中的令牌 token
        String jwt = request.getHeader("token");
        //4.判断令牌是否存在,如果不存在,返回错误结果,未登录
        if(!StringUtils.hasLength(jwt)){
            Result error = Result.error("NOT_LOGIN");
            //对象--JSON
            String notLogin = JSONObject.toJSONString(error);
            response.getWriter().write(notLogin);
            log.info("令牌不存在");
            return;
        }
        //5.解析token 解析失败返回
        try { //快捷键ctrl+alt+t
            JwtUtils.parseJwt(jwt);
        } catch (Exception e) {
            e.printStackTrace();
            Result error = Result.error("NOT_LOGIN");
            //对象--JSON
            String notLogin = JSONObject.toJSONString(error);
            response.getWriter().write(notLogin);
            log.info("token解析失败");
            return;
        }
        //6.放行
        log.info("放行");
        filterChain.doFilter(servletRequest,servletResponse);
    }
}

拦截器 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:放行
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        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 {
       
    }
}

import com.example.demo.filter.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("/**");
    }
}

拦截路径
在这里插入图片描述
在这里插入图片描述

拦截器-执行流程

在这里插入图片描述

登录校验Interceptor登录拦截
@Component
@Slf4j
public class LoginCheckInterceptor implements HandlerInterceptor {
    @Override //目标资源方法运行前返回true:放行
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
       

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

    }
}

异常处理

全局异常处理器
在这里插入图片描述

@RestControllerAdvice
public class GlobalExceptionHandler {
    @ExceptionHandler(Exception.class)
    public Result ex(Exception ex) {
       ex.printStackTrace();
       return Result.error("对不起,操作失败,请联系管理员");
    }
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值