需求:
用户未登录时,访问其他也没面,操作添加、删除等操作时,强行跳转至登录页面。
实现方法:
1.使用Cookie,登录后后端添加一个cookie,每次页面判断是否有cookie,
2。使用session,原理同上,只不过session是存储在服务器里的,cookie是在浏览器里。
3。使用jwt令牌,登录成功后,后端传回一个jwt密钥令牌,浏览器存储在本地,每次请求后端时,将jwt放在请求头中传回后端。
后端如何判断是登录还是查询等操作呢?
这里可以使用两种方法:
1、过滤器:属于wep技术,在项目中设置过滤器:
package com.quxiao.controller;
import com.quxiao.util.JwtUtil;
import lombok.extern.slf4j.Slf4j;
import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Map;
/**
* @program: SpringBoot4
* @author: quxiao
* @create: 2023-04-22 17:20
**/
@Slf4j
@WebFilter(urlPatterns = "/*")
public class CheckFilter implements Filter {
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
//设置允许跨域
HttpServletRequest httpServletRequest = (HttpServletRequest) servletRequest;
HttpServletResponse httpServletResponse = (HttpServletResponse) servletResponse;
httpServletResponse.setHeader("Access-Control-Allow-Origin", "*"); // 允许跨域的地址为所有
httpServletResponse.addHeader("Access-Control-Max-Age", "3600"); // 非简单请求,只要第一次通过OPTIONS检查 在1小时之内不会在调用OPTIONS进行检测
httpServletResponse.setHeader("Access-Control-Allow-Credentials", "true");
String tock = httpServletRequest.getHeader("tock");
String s = httpServletRequest.getRequestURL().toString();
//为登录
if (s.contains("login")) {
filterChain.doFilter(servletRequest, servletResponse);
} else {
//不为登录,判断令牌
if (tock != null && tock.length() != 0) {
JwtUtil jwtUtil = new JwtUtil();
//判断令牌有安全性
if (jwtUtil.checkJwt(tock)) {
filterChain.doFilter(servletRequest, servletResponse);
} else {
log.info("令牌安全性有误");
}
} else {
//无令牌,没登陆
servletResponse.getWriter().write("{\"code\":0,\"msg\":0,\"data\":\"NOT_LOGIN\"}");
}
}
}
}
还要再启动类上加上 Servlet的扫描注解:
ServletComponentScan
拦截器:属于Spring技术:
package com.quxiao.controller.Interceptor;
import com.quxiao.util.JwtUtil;
import lombok.extern.slf4j.Slf4j;
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;
/**
* @program: SpringBoot4
* @author: quxiao
* @create: 2023-04-23 09:18
**/
@Component
@Slf4j
public class LoginCheckInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object handler) throws Exception {
httpServletResponse.setHeader("Access-Control-Allow-Origin", "*"); // 允许跨域的地址为所有
httpServletResponse.addHeader("Access-Control-Max-Age", "3600"); // 非简单请求,只要第一次通过OPTIONS检查 在1小时之内不会在调用OPTIONS进行检测
httpServletResponse.setHeader("Access-Control-Allow-Credentials", "true");
String tock = httpServletRequest.getHeader("tock");
String s = httpServletRequest.getRequestURL().toString();
//为登录
if (s.contains("login")) {
return true;
} else {
//不为登录,判断令牌有效性
if (tock != null && tock.length() != 0) {
JwtUtil jwtUtil = new JwtUtil();
//判断令牌有安全性
if (jwtUtil.checkJwt(tock)) {
return true;
} else {
log.info("令牌安全性有误");
}
} else {
//无令牌,没登陆
httpServletResponse.getWriter().write("{\"code\":0,\"msg\":0,\"data\":\"NOT_LOGIN\"}");
}
}
return false;
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
System.out.println("准备返回前端");
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
System.out.println("全部完成了");
}
}
这两种可以同时出现,执行顺序是:
浏览器——>过滤器——>selevt——>拦截器——>执行请求
浏览器<——过滤器<——selevt<——拦截器<——执行请求
异常处理:遇到异常后,传回指定数据。
package com.quxiao.config;
import com.quxiao.util.ReturnData;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
/**
* @program: SpringBoot4
* @author: quxiao
* @create: 2023-04-23 14:44
**/
@RestControllerAdvice
public class ExceptionClass {
@ExceptionHandler(Exception.class)
public ReturnData ex(Exception ex) {
ex.printStackTrace();
return new ReturnData(0, "发生了错误,请联系管理员", null);
}
}