学习杂记

@EuqalsAndHashCode

lombok插件的注解、

@EqualsAndHashCode(callSuper = false)

此注解会生成equals(Object other) 和 hashCode()方法。
1.它默认使用非静态,非瞬态(transient)的属性。
2.默认不使用父类的属性,即callSuper默认为false
3.指定为true则在1的基础上调用父类的方法

@Valid和@Validated

javax提供了@Valid(标准JSR-303规范)
@Validated是@Valid 的一次封装,是Spring提供的校验机制使用。@Valid不提供分组功能

都可以作用在类、字段、参数上进行检验

当作用在参数上时:通过对标注有@Valid或者@Validated的JavaBean进行校验,并将校验结果封装在BindResult中。注意这个BindResult必须是紧接着的下一个参数。

<!--由于SpringBoot 2.3版本默认移除了校验功能,如果想要开启的话需要添加如下依赖。-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-validation</artifactId>
        </dependency>

作用在参数上的示例

@Data
@EqualsAndHashCode(callSuper = false)
@AllArgsConstructor
@NoArgsConstructor
public class User {
    @Min(value = 100,message = "id必须大于100")
    private long id;
    private String name;    
}
    @GetMapping("/check")
    public ResponseEntity<String> checkUser(@Valid User user, BindingResult result) {
        if (result.hasErrors()) {
            List<ObjectError> allErrors = result.getAllErrors();
            allErrors.stream().forEach(System.out::println);
            return ResponseEntity.badRequest().body("id必须大于100");
        }
        return ResponseEntity.ok("hello");
    }

常用校验注解     属于javax.validation.constraints
@Null 被注释的元素必须是null
@NotNull 被注释的元素不能为null
@AssertFalse 被注释的元素必须为false
@AssertTrue 被注释的元素必须是true
  
(字符串/数组/集合)校验:
@Pattern(regexp=“reg”) 被注释的元素必须符合给定的正则表达式
@Size(max, min) 被注释的元素的长度必须在范围内
@NotEmpty 被注释的元素不为空或者null
@NotBlank 被注释的元素不为null或者trim()后不为空
  
数值校验:
@Max(value) 被注释的元素必须是一个数字,并且小于或者等于指定的int值
@Min(value) 被注释的元素必须是一个数字,并且大于或等于指定的int值
@DecimalMax(value) 被注释的元素必须是一个数字,并且小于或者等于指定的值
@DecimalMin(value) 被注释的元素必须是一个数字,并且大于或等于指定的值
@Digits(integer, fraction) 被注释的元素必须是一个数字, 精整数度小于等于integer;小数部分精度小于fraction
@Range(min=long1, max=long2) 被注释的元素必须是一个数字,其值必须>=long1,并且<=long2
  
日期校验:Date/Calendar
@Post 被注释的元素必须是一个过去的日期
@Future 被注释的元素必须是一个未来的日期

当校验失败时,SpringBoot默认会抛出MethodArgumentNotValidException或BindException异常,我们只要全局处理该异常依然可以得到校验失败信息。

@ResponseEntity

ResponseEntity标识整个http相应:状态码、头部信息以及相应体内容。因此我们可以使用其对http响应实现完整配置。

@GetMapping("/hello")
ResponseEntity<String> hello() {
    return new ResponseEntity<>("Hello World!", HttpStatus.OK);
    // return ResponseEntity.ok("Hello World!");
}
@GetMapping("/age")
ResponseEntity<String> age(
  @RequestParam("yearOfBirth") int yearOfBirth) {

    if (isInFuture(yearOfBirth)) {
        return new ResponseEntity<>(
          "Year of birth cannot be in the future", 
          HttpStatus.BAD_REQUEST);
    }

    return new ResponseEntity<>(
      "Your age is " + calculateAge(yearOfBirth), 
      HttpStatus.OK);
    /** 
    if (isInFuture(yearOfBirth)) {
        return ResponseEntity.badRequest()
            .body("Year of birth cannot be in the future");
    }

    return ResponseEntity.status(HttpStatus.OK)
        .body("Your age is " + calculateAge(yearOfBirth));
    **/

}
@GetMapping("/customHeader")
ResponseEntity<String> customHeader() {
    HttpHeaders headers = new HttpHeaders();
    headers.add("Custom-Header", "foo");

    return new ResponseEntity<>(
      "Custom header set", headers, HttpStatus.OK);
    /**
        return ResponseEntity.ok()
        .header("Custom-Header", "foo")
        .body("Custom header set");  
    **/
}

ResponseStatus

@ResponseStatus的作用是改变HTTP响应的状态码,使用范围:RequestMapping、ExceptionHandler、自定义异常类。

@GetMapping("/check")
@ResponseStatus(value = HttpStatus.BAD_REQUEST, reason = "test")
public ResponseEntity<String> check() {...

@Order

注解可以作用在类、方法、字段声明(包括枚举常量);

@Order 用来控制优先级的,越小优先级越高。默认值为Integer.MAX_VALUE,即最低优先级。
需要注意的是@Order不能控制Bean加载顺序,但是对依赖注入的顺序有影响。

You can declare the @Order annotation at the target class level and on @Bean methods, potentially for individual bean definitions (in case of multiple definitions that use the same bean class). @Order values may influence priorities at injection points, but be aware that they do not influence singleton startup order, which is an orthogonal concern determined by dependency relationships and @DependsOn declarations.

常见的用法还有当定义了多个@ControllerAdivce或者多个@Aspect时,使用@Order指定异常处理或者切面的优先级

RSA算法

RSA是一种非对称加密算法

(1)乙方生成两把密钥(公钥和私钥)。公钥是公开的,任何人都可以获得,私钥则是保密的。
(2)甲方获取乙方的公钥,然后用它对信息加密。
(3)乙方得到加密后的信息,用私钥解密。

如果公钥加密的信息只有私钥解得开,那么只要私钥不泄漏,通信就是安全的。

这种算法非常可靠,密钥越长,它就越难破解。根据已经披露的文献,目前被破解的最长RSA密钥是768个二进制位。也就是说,长度超过768位的密钥,还无法破解(至少没人公开宣布)。因此可以认为,1024位的RSA密钥基本安全,2048位的密钥极其安全

URI和URL

URI = Uniform Resource Identifier 统一资源标识符
URL = Uniform Resource Locator 统一资源定位符
URN = Uniform Resource Name 统一资源名称

URI 在于I(Identifier)是统一资源标示符,可以唯一标识一个资源。
URL在于Locater,一般来说(URL)统一资源定位符,可以提供找到该资源的路径,
比如https://www.zhihu.com/question/21950864
但URL又是URI,因为它可以标识一个资源,所以URL又是URI的子集。
总的来说,locators are also identifiers, so every URL is also a URI, but there are URIs which are not URLs.

HTTP请求报文和响应报文

请求报文

HTTP请求报文由3部分组成(请求行+请求头+请求体)。请求头和请求体之间存在一行空行

在这里插入图片描述

响应报文

HTTP响应报文主要由状态行、响应头部、响应正文3部分组成
在这里插入图片描述

@ModelAttribute

作用范围:方法和参数

示例

被@ModelAttribute注释的方法会在此controller每个方法执行前被执行,因此对于一个controller映射多个URL的用法来说,要谨慎使用。

        @ModelAttribute
        public Account addAccount(@RequestParam String number) {
            return accountManager.findAccount(number);
        }
      
        @RequestMapping(value = "/helloWorld")
        public String helloWorld() {
           return "helloWorld";
        }

addAccount方法在helloWorld方法之前先被调用,在这种情况,model属性的名称没有指定,它由返回类型隐含表示,如这个方法返回Account类型,那么这个model属性的名称是account,属性值为方法返回值。在它执行后helloWorld被调用。
也可以通过 @ModelAttribute(“attributeName”)指定model属性的名称

        @ModelAttribute("user")
        public User addAccount() {
           return new User("a","123");
        }
 
        @RequestMapping(value = "/helloWorld")
        public String helloWorld(@ModelAttribute("user") User user) {
           return "helloWorld";
        }

作用于参数时,可以获取model中的属性值。
此时如果方法体没有标注@SessionAttributes(“user”),那么scope为request,如果标注了,那么scope为session

一个字节(byte)等于8位(bit)
16位系统中,一个字等于16位,即2个字节
32位系统中,一个字等于32位,即4个字节
64位系统中,一个字等于64位,即8个字节

字是计算机一次处理数据的最大单位。多数情况下,这有几个含义:
CPU的寄存器的长度是一个字;
CPU一个指令最多从内存中读取的数据量就是一个字;
最大的寻址空间,是2^字长(如果一个字是64位,那么最大的寻址空间就是2的64次方)

基本类型    大小     取值范围     装箱基本类型
int      4个字节    -2^31 ~ 2^31-1    Integer
char     2个字节              Character
byte     1个字节     -2^7 ~ 2^7-1     Byte
short     2个字节    -2^15 ~ 2^15-1     Short
long     8个字节    -2^63 ~ 2^63-1     Long
float     4个字节               Float
double    8个字节               Double
boolean    4个字节     true ~ false      Boolean

MD5

MD5即Message-Digest Algorithm 5(信息-摘要算法5),是一种不可逆的加密规则算法,比如将敏感信息的密码MD5加密后存储到数据库。用于确保信息传输完整一致。是计算机广泛使用的杂凑算法之一(又译摘要算法、哈希算法),主流编程语言普遍已有MD5实现。将数据运算为另一固定长度值,是杂凑算法的基础原理,MD5的前身有MD2、MD3和MD4。
MD5的作用是让大容量信息在用数字签名软件签署私人密钥前被"压缩"成一种保密的格式(就是把一个任意长度的字节串变换成一定长的十六进制数字串)。
  
MD5算法具有这些特点:
压缩性,任意长度的数据,算出的MD5值长度都是固定的(通常32位的16进制字符串);容易计算,从原数据计算出MD5值很容易;
抗修改性,对原数据进行任何改动,哪怕只修改1个字节,所得到的MD5值都有很大区别;
强抗碰撞,已知原数据和其MD5值,想找到一个具有相同MD5值的数据(即伪造数据)是非常困难的。

MD5加密的特点主要有以下几点:
  1、针对不同长度待加密的数据、字符串等等,其都可以返回一个固定长度的MD5加密字符串。(通常32位的16进制字符串,即128bits);
  2、其加密过程几乎不可逆,除非维护一个庞大的Key-Value数据库来进行碰撞破解,否则几乎无法解开。
  3、运算简便,且可实现方式多样,通过一定的处理方式也可以避免碰撞算法的破解。
  4、对于一个固定的字符串。数字等等,MD5加密后的字符串是固定的,

public class Main {
    public static void main(String[] args) throws Exception {
        // 创建一个MessageDigest实例:
        MessageDigest md = MessageDigest.getInstance("MD5");
        md.update("Hello".getBytes("UTF-8"))
        byte[] result = md.digest(); 
        //把它转换为十六进制的字符串。
        System.out.println(new BigInteger(1, result).toString(16));
    }
}
//32位16进制的字符串
//sout:f5a7924e621e84c9280a9a27e1bcb7f6

@Import

只能作用在类上

@Import注解可以把指定的类加入spring的IOC容器中,注入的Bean id为全类名。

支持的类

1.带有@Configuration的配置类(4.2 版本之前只可以导入配置类,4.2版本之后可以导入普通类
2.ImportSelector 接口的实现类     [返回需要导入的组件的全类名数组;]
3.ImportBeanDefinitionRegistrar 接口的实现类  [实现手动注册bean到容器中]

可以用于第三方依赖包中Bean的加载

spring.profiles.active

spring boot允许你通过命名约定按照一定的格式(application-{profile}.properties)来定义多个配置文件(bootstarp同理)。然后通过spring.profiles.active来具体激活一个或者多个配置文件,如果没有没有指定任何profile的配置文件的话,spring boot默认会启动application-default.properties。

@ConfigurationProperties

spring-boot 提供该注解将配置文件的值映射到类上的字段。可以通过prefix属性指定配置文件中的属性前缀

示例

secure:
  ignore:
    urls: #配置白名单路径
      - "/swagger-resources/**"
      - "/swagger/**"
      - "/**/v2/api-docs"
 /**
  * 网关白名单配置
 * Created by macro on 2020/6/17.
 */
@Data
@EqualsAndHashCode(callSuper = false)
@Component
@ConfigurationProperties(prefix="secure.ignore")
public class IgnoreUrlsConfig {
    private List<String> urls;
}

cookie、session、token

https://blog.csdn.net/javaQQ561487941/article/details/89554225

HTTP协议本身是无状态的,客户只需要简单的向服务器来发送请求下载某些文件,客户端向服务器端发送的每次请求都是独立的。对于当前的web应用,HTTP的“无状态”,导致许多应用都不得不花费大量的精力来记录用户的操作步骤。

cookie 是一个非常具体的东西,指的就是浏览器里面能永久存储的一种数据,仅仅是浏览器实现的一种数据存储功能。
cookie由服务器生成,发送给浏览器,浏览器把cookie以kv形式保存到某个目录下的文本文件内,下一次请求同一网站时会把该cookie发送给服务器。cookie 是不可跨域的: 每个 cookie 都会绑定单一的域名,无法在别的域名下获取使用,一级域名和二级域名之间是允许共享使用的(靠的是 domain)。

当用户第一次通过浏览器使用用户名和密码访问服务器时,服务器会验证用户数据,验证成功后在服务器端写入session数据,向客户端浏览器返回sessionid(jsessionid),浏览器可以将sessionid保存在cookie中,当用户再次访问服务器时,会携带sessionid,服务器会拿着sessionid获取session数据,从而实现状态保持。

对于token:
①认证成功后,会对当前用户数据进行加密,生成一个加密字符串token,返还给客户端
(服务器端可以保存在缓存或者数据库,如果使用的是jwt的话就无需保存,因为jwt具有自解释性)
再次访问时只需携带token,服务器校验浏览器传来的token

CSRF

CSRF全称为跨站请求伪造(Cross-site request forgery),是一种网络攻击方式,也被称为 one-click attack 或者 session riding。
简单来说就是: 你访问了信任网站 A,然后 A 会用保存你的个人信息并返回给你的浏览器一个cookie,然后呢,在 cookie 的过期时间之内,你去访问了恶意网站 B,它给你返回一些恶意请求代码,要求你去访问网站 A,而你的浏览器在收到这个恶意请求之后,在你不知情的情况下,会带上保存在本地浏览器的 cookie 信息去访问网站 A,然后网站 A 误以为是用户本身的操作,导致来自恶意网站 B 的请求会被执行。
在这里插入图片描述

解决方案

使用验证码

关键操作页面加上验证码,后台收到请求后通过判断验证码可以防御CSRF。但这种方法对用户不太友好。

使用token

CSRF 攻击之所以能够成功,是因为黑客可以完全伪造用户的请求,该请求中所有的用户验证信息都是存在于cookie中,因此黑客可以在不知道这些验证信息的情况下直接利用用户自己的cookie 来通过安全验证。要抵御 CSRF,关键在于在请求中放入黑客所不能伪造的信息,并且该信息不存在于 cookie 之中。

参考

https://blog.csdn.net/neweastsun/article/details/81142870
https://www.zhihu.com/question/21950864
https://blog.csdn.net/javaQQ561487941/article/details/89554225

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值