登录(六) 会话技术 会话 :用户打开浏览器,访问web服务器的资源,会话建立,直到有一方断开连接,会话结束,在一次会话中可以包含多次请求和响应。
会话跟踪 :一种维护浏览器状态的方法,服务器需识别多次请求是否来自同一浏览器,以便在同一次会话的多次请求见共享数据。
会话跟踪方案 :
客户端会话跟踪技术:Cookie
服务端会话跟踪技术:Session
令牌技术
Cookie 优点 :http协议中支持的技术。
缺点 :
移动端APP无法使用Cookie
不安全,用户可以自己禁用Cookie
Cookie不能跨域
Session 优点 :存储在服务器,安全。
缺点 :
服务器集群环境下无法直接使用Session
Cookie的缺点
令牌技术 优点 :
支持PC,移动端
解决集群环境下的认证问题
减轻服务器端存储压力
缺点 :需自己实现
JWT JWT 全程JSON Web Token。
定义一组简洁的,自包含的格式,用于在通信双方以JSON数据格式安全的传递信息。由于数据签名的存在,这些信息是可靠的。
组成 :
Header(头),记录令牌类型,签名算法。
Payload(有效荷载):携带一些自定义信息,默认信息等。
Signature(签名),防止Token被篡改,确保安全性,将header,payload,并加入指定秘钥,通过指定签名算法计算而来。
使用场景 :登录认证
登录认证
登录成功后,生成令牌。
后续每个请求,都要携带JWT令牌,系统在每次请求处理之前,先校验令牌,通过后,再处理
依赖 1 2 3 4 5 <dependency> <groupId>io.jsonwebtoken</groupId> <artifactId>jjwt</artifactId> <version>0.9.1</version> </dependency>
生成和校验 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 //生成 @Test void jwtGenerate(){ Map<String,Object> map=new HashMap<>(); map.put("a",1); map.put("b",2); String ljsblog = Jwts.builder() .setClaims(map) .signWith(SignatureAlgorithm.HS256, "ljsblog") .setExpiration(new Date(System.currentTimeMillis()+1000*3600*12))//一天后失效 .compact(); System.out.println(ljsblog); } //校验 @Test void jwtCertify(){ Claims ljsblog = Jwts.parser() .setSigningKey("ljsblog") .parseClaimsJws("eyJhbGciOiJIUzI1NiJ9.eyJhIjoxLCJiIjoyLCJleHAiOjE2ODQzNTc4NzV9.jr-x-QlFpVgt44kc-8Mfyduzd_m10jb7pwhyxPtYfwQ") .getBody(); System.out.println(ljsblog); }
注 :
JWT校验时使用的签名秘钥,必须和生成JWT令牌时使用的秘钥配套
若JWT令牌解析校验时报错,则说明JWT令牌被纂改或失效,令牌非法
Filter过滤器 Filter过滤器 :是Javaweb三大组件(Servlet,Filter,Listener)之一。
过滤器可把资源的请求拦截下来,从而实现一些特殊功能。
过滤器一般完成一些通用操作,比如:登录校验,统一编码处理,敏感字符处理等。
Filter快速入门
定义Filter
定义一个类,实现Filter接口,并重写其所有方法
配置Filter
Filter类加@WebFilter注解,配置拦截资源的路径,引导类加上@ServletComponentScan开启Servlet组建支持。
例 :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 package com.ljsblog.file; 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 { } @Override public void destroy() { Filter.super.destroy(); } } package com.ljsblog; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.web.servlet.ServletComponentScan; @ServletComponentScan @SpringBootApplication public class TliasWebManagmentApplication { public static void main(String[] args) { SpringApplication.run(TliasWebManagmentApplication.class, args); } }
Filter拦截路径
拦截具体路径
urlPatterns值:/路径名
只有访问/路径名时,才会被拦截
目录拦截
urlPatterns值:/路径名/*
访问/路径名下的所有资源,都会被拦截
拦截所有
urlPatterns值:/*
访问所有资源,都会被拦截
执行流程
请求
放行前逻辑
放行
资源
放行后逻辑
过滤器链 一个web应用中,配置多个过滤器,就形成一个过滤器链
顺序 :注解配置的Filter,优先级是按照过滤器类名(字符串)的自然排序
登录校验filter 注 :
除了登录请求,其余请求拦截到都需要校验令牌
拦截到请求后,有令牌且令牌校验通过(合法)才可以放行,否则都会返回登录错误结果
流程 :
获取请求url
判断请求url中是否包含login,若包含,说明是登录操作,放行。
获取请求头中的令牌(token)
判断令牌时否存在,若不存在,返回错误结果(未登录)
解析token,若解析失败,返回错误结果(未登录)
放行
拦截器 拦截器 是一种动态拦截方法调用的机制,类似于过滤器,Spring框架中提供的,用来动态拦截控制器方法的执行,可用来拦截请求,在指定的方法调用前后,根据业务需要执行预先设定的代码。
Interceptor快速入门
定义拦截器,实现HandlerInterceptor接口,并重写其所有方法
注册拦截器
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 @Component public class CheckInterceptor 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"); } } @Configuration public class WebConfig implements WebMvcConfigurer{ @Autowired private CheckInterceptor checkInterceptor; @Override public void addInterceptors(InterceptorRegistry registry) { registry.addInterceptor(checkInterceptor).addPathPatterns("/**").excludePathPatterns("/login"); } }
拦截路径 addPathPatterns:需要拦截的资源。
excludePathPatterns:不需要拦截的资源。
拦截路径:/*
拦截路径:/**
拦截路径:/路径名/*
拦截路径:/路径名/**
Filter和Interceptor的区别
接口规范不同
过滤器需要实现Filter接口
拦截器需要实现HandlerInterceptor接口
拦截范围不同
过滤器会拦截所有资源
拦截器只拦截Spring环境中的资源
全局异常处理器 1 2 3 4 5 6 7 8 9 @RestControllerAdvice public class GlobalExceptionHandler { @ExceptionHandler(Exception.class) public Result ex(Exception ex){ ex.printStackTrace(); return Result.error("操作失败,请联系管理员"); } }