8.SpringBoot配置,登录校验

SpringBoot配置,登录校验

SpringBoot配置

配置格式:

SpringBoot提供了多种属性配置方式:

application.properties
  • 是使用.号来分级的
server.port=8080
server.address=127.0.0.1
application.yml/application.yaml(推荐)
基本语法:
大小写敏感;
数值前边必须有空格,作为分隔符;
使用缩进表示层级关系,缩进时,不允许使用Tab键,只能用空格(idea中会自动将Tab转换为空格);
缩进的空格数目不重要,只要相同层级的元素左侧对齐即可;
#表示注释,从这个字符一直到行尾,都会被解析器忽略;
数据格式:
  • 对象/Map集合:
user:
  name: zhangsan
  age: 18
  password: 123456
  • 数组/List/Set集合:
hobby:
  - java
  - game
  - sport
例子:
#spring配置
spring:
  #数据库连接
  datasource:
    #驱动类名称
    driver-class-name: com.mysql.cj.jdbc.Driver
    #数据库连接的url,mybatis为数据库名
    url: jdbc:mysql://localhost:3306/tlias
    #连接数据库的用户名
    username: root
    #连接数据库的密码
    password: 123456
  #文件上传的配置
  servlet:
    multipart:
      #配置单个文件最大上传大小
      max-file-size: 10MB
      #配置单个请求最大上传大小(一次请求可以上传多个文件)
      max-request-size: 100MB

#mybatis配置
mybatis:
  configuration:
    #指定mybatis输出日志的位置,输出控制台
    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
    #开启驼峰命名:如果字段名与属性名符合驼峰命名规则,mybatis会自动通过驼峰命名规则映射
    map-underscore-to-camel-case: true

#配置服务器
server:
  port: 8080
  address: 127.0.0.1

#自定义参数
#自定义的阿里云OSS配置信息
aliyun:
  oss:
    endpoint: https://oss-cn-beijing.aliyuncs.com
    accessKeyId: LTAI5tFG6HzT3D1pEVP4sF1y
    accessKeySecret: g4cgQQXSbPXi3ZLg4RqT6bREYZIhVt
    bucketName: caihongjia-web-tlias

application参数配置化

概念:

将需要反复使用的参数,通过key=value的方式写在application.properties配置文件中;
key可以自定义名称,但是在项目中尽量定义的有一定的业务含义;

定义例子:

  • application.properties
#自定义的阿里云OSS配置信息
aliyun.oss.endpoint=https://oss-cn-beijing.aliyuncs.com
aliyun.oss.accessKeyId=LTAI5tFG6HzT3D1pEVP4sF1y
aliyun.oss.accessKeySecret=g4cgQQXSbPXi3ZLg4RqT6bREYZIhVt
aliyun.oss.bucketName=caihongjia-web-tlias

注入:

@Value
用来注入外部配置的属性的;
只能一个一个的进行外部属性的注入;
写在每个需要注入的属性名上;
写法: @Value("${配置文件中的key}")
@ConfigurationProerties
用来注入外部配置的属性的;
可以批量的将外部的属性配置注入到bean对象的属性中;
在对应javabean类上,需要
	get和set方法;
	@Component注解,交由IOC容器管理;
	@ConfigurationProerties注解;
javabean中的属性名要与配置文件中的属性名一致;
获取对象: 使用依赖注入来获取相应的对象;
写法: @ConfigurationProerties(prefix="前缀名")

注入例子:

@Value
@Value("${aliyun.oss.endpoint}")
private String endpoint;

@Value("${aliyun.oss.accessKeyId}")
private String accessKeyId;

@Value("${aliyun.oss.accessKeySecret}")
private String accessKeySecret;

@Value("${aliyun.oss.bucketName}")
private String bucketName;
@ConfigurationProperties

登录校验:

登录标记:

  • 会话技术;
  • 用户登录成功之后,每一次请求中,都可以获取到该标记;

会话技术:

概念:

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

会话跟踪:

概念:
  • 一种维护浏览器状态的方法,服务器需要识别多次请求是否来自于同一浏览器,以便在同一次会话的多次请求间共享数据
客户端会话跟踪技术:Cookie
介绍:
  • 概念:是使用请求头传递的;

  • 优点:HTTP协议中支持的技术,属于浏览器提供的技术;

  • 缺点:

    • 移动端APP无法使用Cookie
    • 不安全,用户可以自己禁用Cookie
    • Cookie不能跨域
  • 跨域区分三个维度:协议、IP/域名、端口

使用:
  • 请求(获取Cookie):
使用(HttpServletRequest request)中的getCookies()方法获取所有的Cookie;
使用getName()获取Cookie的名字;
使用getValue()获取Cookie的值;
  • 响应(设置Cookie):
使用(HttpServletResponse response)中的addCookies(参数)方法设置一个Cookie;
参数为: new Cookie(Cookie名,Cookie值);
服务端会话跟踪技术:Session
介绍:
  • 概念:将数据存在Session中,然后将对应的id放入Cookie中传递;
  • 优点:存储在服务端,安全
  • 缺点:
    • 服务器集群环境下无法直接使用Session
    • Cookie的缺点
使用:
  • 请求/响应:
使用(HttpServletRequest request)中的getSession()方法获取所有的Session对象;
或者直接使用(HttpSession session)来代表Session对象;
获取: 使用getAttribute(session名)获取对应session的值;
设置: 使用setAttribute(session名,session值)来设置session;
令牌技术:
优缺点:
  • 优点:
    • 支持PC端、移动端;
    • 解决集群环境下的认证问题;
    • 减轻服务器存储压力;
  • 缺点:需要自己实现;
JWT令牌简介:
  • 全称:JSON Web Token(https://jwt.io/)
  • 定义了一种简洁的、自包含的格式,用于在通信双方以json数据格式安全的传输信息。由于数字签名的存在,这些信息是可靠的;
JWT令牌组成:
  • 由三部分组成,由点号分割;

  • Base64:是一种基于64个可打印字符(A-Z a-z 0-9 + /)来表示二进制数据的编码方式;=号用作补位;

  • 第一部分:Header(头),记录令牌类型、签名算法等。例如:["alg":"HS256","type":"JWT"];使用Base64将其编码;

  • 第二部分:Payload(有限载荷),携带一些自定义信息、默认信息等。例如:["id":"1","username":"Tom"];使用Base64将其编码;

  • 第三部分:Signature(签名),防止Token被篡改、确保安全性。将header、payload,并加入指定密钥,通过指定签名算法计算而来;没有使用Base64

  • 例子:

JWT使用场景:
  • 登录认证:
    1. 登录成功后,生成令牌;
    2. 后续每个请求,都要携带JWT令牌,系统在每次请求处理之前,先校验令牌。通过后,再处理;
引入JWT依赖:
<!--JWT令牌-->
<dependency>
    <groupId>io.jsonwebtoken</groupId>
    <artifactId>jjwt</artifactId>
    <version>0.9.1</version>
</dependency>
JWT生成:
public void genJwt(){
	Map<String,Object> claims = new HashMap<>();
	claims.put("id",1);
	String jwt = jwts.builder()
		.setClaims(claims)//自定义内容(载荷)
		.signWith(SignatureAlgorithm.HS256,"caihongjia")//签名算法: 参数1:加密算法;参数2:自定义密钥
		.setExpiration(new Date(System.currentTimeMillis() + 3600*1000))//有效期
		.compact();

}
JWT校验:
public void parseJwt(){
	Claims claims = Jwts.parser()
		.setSigningKey("caihongjia")//指定签名密钥
		.parseClaimsJws("生成的令牌")//解析令牌
		.getBody();
		
}
注意事项:
  • JWT校验时使用的签名秘钥,必须和生成JWT令牌时使用的秘钥是配套的;
  • 如果JWT令牌解析校验时报错,则说明JWT令牌被篡改或失效了,令牌非法;

统一拦截:

跨域ajax请求:

概念:
  • 复杂的跨域ajax请求,浏览器会先发送一个OPTIONS请求,确认是可以请求的,之后才发送我们真正的get或者post等定义的请求;
  • OPTIONS请求,headers是不会带过来的,所以过滤器中是要跳过这种请求的;
处理方法:
if("OPTIONS".equals(request.getMethod())) {
	filterChain.doFilter(servletRequest,servletResponse);
}

ServerLet:过滤器Filter

概述:
  • 概念:Filter过滤器,是JavaWeb三大组件(Servlet、Filter、Listener)之一;
  • 过滤器可以把对资源的请求拦截下来,从而实现一些特殊的功能;
  • 过滤器一般完成一些通用的操作,比如:登录校验、统一编码处理、敏感字符处理等;
定义与配置:
  • 定义Filter:定义一个类,实现Filter接口,并重写其所有方法;
  • 配置Filter:Filter类上加@WebFilter(urlPatterns="/*")注解,配置拦截资源的路径。引导类上加@ServletComponentScan开启Servlet组件支持;
  • 三大方法:
    • init:初始化方法,Web服务器启动,创建Filter调用,只调用一次;不常用;
    • doFilter:拦截到请求时,调用该方法,可调用多次;最常用;
      • 使用chain.doFilter(request,response);方法来放行;
    • destroy:销毁方法,服务器关闭时调用,只调用一次;不常用;
过滤器详解:
  1. 执行流程:
    • 请求 --> 放行前逻辑 --> 放行 --> 资源 --> 放行后逻辑
  2. 拦截路径:
    • /login:拦截login路径
    • /depts/*:拦截depts路径下的任意路径,包括该路径下的一、二级路径及以上路径;
    • /*:拦截任意路径,包括一、二级路径及以上路径;
  3. 过滤器链:
    • 一个web应用中,配置了多个过滤器,就形成了一个过滤器链;
    • 顺序:注解配置的Filter,优先级是按照过滤器类名(字符串)的自然排序;

spring:拦截器Interceptor

概述:
  • 概念:是一种动态拦截方法调用的机制,类似于过滤器。Spring框架中提供的,用来动态拦截控制器方法的执行;
  • 作用:拦截请求,在指定的方法调用前后,根据业务需要执行预先设定的代码;
定义与注册:
定义拦截器:
  • 实现HandlerInterceptor接口,并重写其所有方法;
  • 将定义的拦截器:加@Component注解,放入IOC容器中;
  • 三个方法:
    • preHandle方法:目标资源方法执行前执行,返回true:表示放行,返回false:表示不放行;
    • postHandle方法:目标资源方法执行后执行;
    • afterCompletion方法:视图渲染完毕后执行,最后执行;
注册拦截器:
  • 实现WebMvcConfigurer接口,并重写addInterceptors方法;
  • 使用@Autowired注解,来注入需要使用的拦截器;
  • addInterceptor方法指定拦截器:
registry.addInterceptor("需要指定的拦截器").addPathPatterns("需要拦截的路径");
Interceptor拦截器,指定所有路径是"/**";
拦截器-拦截路径:
  • 拦截器可以根据需求,配置不同的拦截路径:
addPathPatterns("/**"):	需要拦截哪些资源;
excludePathPatterns("/login"):	不需要拦截哪些资源;
拦截路径 含义 举例
/* 一级路径 能匹配/depts, /emps, /login, 不能匹配/depts/1
/** 任意级路径 能匹配/depts, /depts/1, /depts/2
/depts/* /depts下的一级路径 能匹配/depts/1, 不能匹配/depts/1/2, /depts
/depts/** /depts下的任意级路径 能匹配/depts, /depts/1, /depts/1/2, 不能匹配/emps/1
  • 例子:
@Override
public void addInterceptors(InterceptorRegistry registry){
	registry.addInterceptor("需要指定的拦截器").addPathPatterns("/**").excludePathPatterns("/login");
}
Filter与Interceptor对比;
  • 接口规范不同:过滤器需要实现Filter接口,而拦截器需要实现HandlerIntercepttor接口;
  • 拦截范围不同:过滤器Filter会拦截所有的资源,而Interceptor只会拦截Spring环境中的资源;

异常处理:

  • 当出现异常时,可以使用全局异常 处理器来处理;
  • 全局异常处理器;
    • 创建一个类,为这个类添加@RestControllerAdvice注解;
    • 在类中添加对应方法,将该方法添加@ExceptionHandler(异常的class)注解,表示处理什么异常;
    • 然后返回标准的结果类;
posted @ 2023-11-24 17:53  回家太晚太悲催  阅读(143)  评论(0)    收藏  举报