记录 积累

语法

替代if

https://blog.csdn.net/Connie1451/article/details/120045474

用策略模式

多线程

volatile

线程池

https://blog.csdn.net/weixin_40598838/article/details/112861491

分布式锁

https://github.com/apache/shardingsphere/issues/5882

禁止安全检查
management:
  health:
    db:
      enabled: false

lock、synchronize 只在单 jvm 有效,多集群 会失效

3中实现方式:

数据库

redis:
redis 的key 唯一

java - jacadoc - inheritdoc

https://blog.csdn.net/weixin_30131185/article/details/115572186

Java - Properties类

https://blog.csdn.net/weixin_53972936/article/details/1238993682

定时任务

https://blog.csdn.net/arjun_yu/article/details/115294665

@Scheduled(cron="${a.b.cron}") 

定时任务 @Scheduled 不启动,解决办法:
https://blog.csdn.net/wenyichuan/article/details/119179364

定时任务 区分不同环境 是否启动
https://blog.csdn.net/qq_31122833/article/details/105431087
配置文件名必须是 application
application-log 就不行

@ConditionalOnProperty(prefix = "sence", name = "isBlue", havingValue = "true")
public class Task {
...
}

application.yml

sence:
  isBlue: true

启动类注解:

@EnableSchedulin
public class Application {
...
}

配置类 不同环境 是否启动

@ConditionalOnProperty(value = "sence.isred")
public class Config {}
sence.isred = true

https://www.cnblogs.com/MrFugui/p/15610746.html

implements Serializable

https://blog.csdn.net/weixin_45410366/article/details/126618512

序列化:将对象状态转换为可保持、传输的格式 = 对象转换为字节序列
反序列化:将流转换为对象 = 字节序列恢复为对象
这两个过程结合起来,可以轻松地存储和传输数据

一个类只有实现了 Serializable 接口,它的对象才是可序列化的

serialVersionUID 的作用:验证序列化和反序列化的过程中,对象是否保持一致

使用场景:
当我们需要把对象的状态信息:
A 通过网络进行传输(用套接字在网络上传送)
B 需要将对象的状态信息持久化(写入硬盘)

Serializable class without ‘serialVersionUID’

双击类名 → alt + enter

数据库

SpringBoot配置多个DataSource

https://juejin.cn/post/6844903957186232327
https://blog.csdn.net/weixin_45155235/article/details/127320435

spring.datasource.db1.driver-class-name=
spring.datasource.db1.jdbc-url=
spring.datasource.db1.username=
spring.datasource.db1.password=

spring.datasource.db2.driver-class-name=
spring.datasource.db2.jdbc-url=
spring.datasource.db2.username=
spring.datasource.db2.password=

单个DataSource

spring.datasource.driver-class-name=
spring.datasource.jdbc-url=
spring.datasource.username=
spring.datasource.password=

数据类型

long 对应 mysql 是 bigint(64)

java 中时间类型是 Date
mysql 中是 datetime

parameterType=“map”

https://blog.csdn.net/weixin_47982446/article/details/121694366

if, choose, where

https://blog.csdn.net/YIEBO/article/details/110881687
https://blog.csdn.net/Sibylsf/article/details/113138380

错误写法:

UPDATE Table_xxx
set Count=Count + 1
where 1=1
<if test="Id>0">
    and Id = #{Id}
</if>
<if test="text !=null">
    and Text = #{text}
</if>

当下面两个if条件都不满足时,会出现:
该表内所有数据都执行count+1,
故where 1=1 这种写法不可取

正确写法:

UPDATE Table_xxx
set Count=Count + 1
<where>
    <if test="Id>0">
        and Id = #{Id}
    </if>
    <if test="text !=null">
        and Text = #{text}
    </if>
</where>

https://ask.csdn.net/questions/7741444
<where> 标签会过滤掉第1个在条件前的and或or,
也就是如果你在emp_name前写了一个and,它会自动过滤掉,后面的不会过滤

https://blog.csdn.net/weixin_38295272/article/details/117753097

dao层注解@repository

https://blog.csdn.net/qq_40088250/article/details/88388715/

查询数量

select a,b,c,d,e,f,g from biao where

java程序查询list,获取list.size(),如果数据量过大,会导致响应慢甚至404
应该 select count(*) from biao

删除数据

一次只删除1000条数据
如果一次删除过多语句(如100万条数据),会影响这条sql语句的执行时间

可以一直删除,直到返回数为0


# {}

#{} 参数占位符,可防止sql注入,带引号
${} 纯 字符串替换,不带引号

!CDATA

https://blog.csdn.net/happy_cheng/article/details/41792985

<select id="find" resultType="JobLogVo">
    <include refid="base"/>
    where t.status='1'
    AND  <![CDATA[ t.createDate <= xxx ]]>
</select>

 <![CDATA[   abc    ]]>
 abc中可以包含 < >
第一种写法(1):

原符号       <        <=      >       >=       &        '        "
替换符号    &lt;    &lt;=   &gt;    &gt;=   &amp;   &apos;  &quot;
例如:sql如下:
create_date_time &gt;= #{startTime} and  create_date_time &lt;= #{endTime}

第二种写法(2):
大于等于
<![CDATA[ >= ]]>
小于等于
<![CDATA[ <= ]]>
例如:sql如下:
create_date_time <![CDATA[ >= ]]> #{startTime} and  create_date_time <![CDATA[ <= ]]> #{endTime}

get post

get 请求,请求链接 放置参数
post 请求 才可以这样,参数不放在链接里:

 search(@RequestBody XXX xx)

多个实现类 spring 怎么选择

https://blog.csdn.net/u010476994/article/details/80986435

public class AnimalController {
    @Autowired
    private IAnimal dogImpl;
    ......
}

@Autowired 的注入方式是 byType 注入,
当要注入的类型在容器中存在多个时,Spring不知道要引入哪个实现类的,会报错
用 @Resource 或 @Qualifier 注解,byName 注入 不报错

public class AnimalController {
    @Resource(name="dogImpl")        //实现类1中 @Service注解中标定的名称
    private IAnimal dogImpl;
    ......
}

public class AnimalController {
    @Qualifier("DaoImpl")        //实现类1的类名。注意区分与@Resource(name="dogImpl") 的区别。
    private IAnimal dogImpl;
    ......
}

配置

https://zhuanlan.zhihu.com/p/357050965

优先级排序

https://juejin.cn/post/6844904100111319054


优先级:4 > 3 > 2 > 1

1 项目在线的配置中心
2 配置文件xxx.properties
3 代码中的配置

4 vm options

配置文件读取流程

http://www.javaboy.org/2019/0530/application.properties.html

resources 目录下创建 javaboy 目录,存放一个 application.properties 文件,
正常情况下,启动 Spring Boot 项目,这个配置文件是不会被自动加载的。
我们可以通过 spring.config.location 属性 指定配置文件位置,系统就会自动去指定目录下查找 application.properties 文件

项目已经打包成 jar ,在启动命令中加入位置参数即可:
java -jar properties-0.0.1-SNAPSHOT.jar --spring.config.location=classpath:/javaboy/

-Dspring.config.name 指定配置文件的文件名,默认是application.properties

属性注入
法1

@Component
@PropertySource("classpath:book.properties")
public class Book {
    @Value("${book.id}")
    private Long id;
    @Value("${book.name}")
    private String name;
    @Value("${book.author}")
    private String author;
}

法2

<context:property-placeholder location="classpath:book.properties"/>
@Component
public class Book {
    @Value("${book.id}")
    private Long id;
    @Value("${book.name}")
    private String name;
    @Value("${book.author}")
    private String author;
}

类型安全的属性注入

@Component
@PropertySource("classpath:book.properties")
@ConfigurationProperties(prefix = "book")
public class Book {
    private Long id;
    private String name;
    private String author;
    //省略getter/setter
}

@ConfigurationProperties(prefix = “book”) ,此时会自动将 Spring 容器中对应的数据注入到对象对应的属性中,不用通过 @Value 注解挨个注入了,减少工作量并且避免出错

不同环境不同配置

application.properties:

spring.profiles.active=test

不同的环境,使用不同的bean

https://blog.csdn.net/u014163312/article/details/117049437

不同环境 方法是否启动

@ConditionalOnProperty(value = "sence.isBlue")

jvm参数 -Dsence.isBlue

maven profile动态选择配置文件

https://www.cnblogs.com/0201zcr/p/6262762.html

xml 转换 properties

https://blog.csdn.net/u010316188/article/details/79598220
https://blog.csdn.net/u010316188/article/details/79598220

lombok 不支持 java10 解决:

<dependency>
    <groupId>org.projectlombok</groupId>
    <artifactId>lombok</artifactId>
    <version>1.18.2</version>
    <scope>provided</scope>
</dependency>

jar名 反推 pom依赖

https://blog.csdn.net/londa/article/details/117906300

spring 配置

https://www.cnblogs.com/relucent/p/9792645.html

win10 的系统变量也可以读取,如果新加了系统变量,idea需要重启才能读取到

dependencyManagement 应用场景

https://blog.csdn.net/vtopqx/article/details/79034835

所有的子模块使用依赖项的统一版本,必须确保应用的各个项目的依赖项和版本一致,才能保证测试的和发布的是相同的结果。
在父pom文件中,dependencyManagement元素 管理jar包的版本,让子项目中引用一个依赖而不用显示的列出版本号。
Maven会沿着父子层次向上走,直到找到一个拥有dependencyManagement元素的项目,然后它就会使用在这个dependencyManagement元素中指定的版本号

父pom

<dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>mysql</groupId>
                <artifactId>mysql-connector-java</artifactId>
                <version>5.1.44</version>
            </dependency>
           
        </dependencies>
</dependencyManagement>
子模块中只需要<groupId>和<artifactId>即可
 <dependencies>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
        </dependency>
 </dependencies>

SpringBoot 读取配置文件

https://blog.csdn.net/sufu1065/article/details/126434530

afterPropertiesSet() 是 Spring 框架中的一个接口,它可以让开发人员在 Bean 实例化后,所有属性被设置后,执行自定义的初始化操作

springboot 密码加解密

https://www.cnblogs.com/hxgoto/p/16281052.html
https://blog.csdn.net/qq_42998034/article/details/115403048

pom

<dependency>
   <groupId>com.github.ulisesbocchio</groupId>
    <artifactId>jasypt-spring-boot-starter</artifactId>
    <version>2.1.2</version>
</dependency>

application.yml

spring:
  data:
    mongodb:
      uri: mongodb://127.0.0.1:27017/bookmark
  datasource:
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://localhost:3306/bookmarksdb3?serverTimezone=UTC&useUnicode=true&characterEncoding=UTF-8
    username: root
#    password: "123456"
    password: ENC(4DE4bFfmmsbqN/X12lrbwQ==)


server:
  port: 8094

jasypt:
  encryptor:
    password: sad124f1f1rf1fgt5
    property:
      prefix: ENC(
      suffix: )
#    iv-generator-classname: org.jasypt.iv.NoIvGenerator

必须是yml文件!
application.properties、environment.properties 配置都不行!

config.xml 关联 application.yml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>

	关联application:
    <properties resource="application.yml"></properties>

    <environments default="development">
        <environment id="development">
            <!-- 配置JDBC事务管理理 -->
            <transactionManager type="JDBC"></transactionManager>
            <!-- POOLED配置JDBC数据源连接池 -->
            <dataSource type="POOLED">
                <property name="driver" value="${driver-class-name}"></property>
                <property name="url"
                          value="${url}"></property>
                <property name="username" value="${username}"></property>
                <property name="password" value="${password}"></property>
                value 对应 yml单个字段,不用写字段前的路径


<!--                <property name="driver" value="${spring.datasource.driver-class-name}"></property>-->
<!--                <property name="url"-->
<!--                          value="${spring.datasource.url}"></property>-->
<!--                <property name="username" value="${spring.datasource.username}"></property>-->
<!--                <property name="password" value="${spring.datasource.password}"></property>-->

                <!--                <property name="password" value="123456"></property>-->

                <!--                <property name="driver" value="com.mysql.cj.jdbc.Driver"></property>-->
                <!--                <property name="url"-->
                <!--                          value="jdbc:mysql://7.205.116.205:3306/book?serverTimezone=UTC&amp;useUnicode=true&amp;characterEncoding=UTF-8"></property>-->
                <!--                <property name="username" value="dbAdmin"></property>-->
                <!--                <property name="password" value="${spring.datasource.password}"></property>-->
            </dataSource>
        </environment>
    </environments>

    <!--    <typeAliases>-->
    <!--        &lt;!&ndash; 扫描包自动映射单个别名 &ndash;&gt;-->
    <!--        &lt;!&ndash; 平台侧 &ndash;&gt;-->
    <!--        <typeAlias alias="BookmarkEntity" type="com.example.entity.BookmarkEntity" />-->
    <!--        <typeAlias alias="BookmarkEntityMysql" type="com.example.entity.BookmarkEntityMysql" />-->

    <!--    </typeAliases>-->

    <mappers>
        <!-- 注册AccountMapper.xml -->
        <mapper resource="com/example/repository/mysqlRepository.xml"></mapper>
    </mappers>

</configuration>

jasypt-1.9.3.jar下载
https://download.csdn.net/download/qq_40893824/88062907

https://blog.csdn.net/qq_21118431/article/details/103551207

加密:

java -cp  jasypt-1.9.3.jar  org.jasypt.intf.cli.JasyptPBEStringEncryptionCLI input="123456" password=sad124f1f1rf1fgt5 algorithm=PBEWithMD5AndDES

解密:

java -cp jasypt-1.9.3.jar org.jasypt.intf.cli.JasyptPBEStringDecryptionCLI input="加密串" password=sad124f1f1rf1fgt5 algorithm=PBEWithMD5AndDES

进阶

https://www.cnblogs.com/toutou/p/Jasypt.html

打包时隐藏jasypt.encryptor.password,就需要打包时maven命令增加参数
clean package -Djasypt.encryptor.password=Bt%XJ^n1j8mz
部署时添加参数 Djasypt.encryptor.password
部署时完整命令 java -jar -Djasypt.encryptor.password=Bt%XJ^n1j8mz hello-0.0.1-SNAPSHOT.jar

读取加密密码

    private SqlSession getSqlSession() throws IOException {
        InputStream inputStream = Mycontroller.class.getClassLoader().getResourceAsStream("config.xml");
        SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();

        InputStream in = Resources.getResourceAsStream("application.properties");
        Properties props = new Properties();
        props.load(in);
        props.put("password", password);

        SqlSessionFactory sqlSessionFactory = sqlSessionFactoryBuilder.build(inputStream, props);
        return sqlSessionFactory.openSession(ExecutorType.BATCH, false);
    }

AES 加解密

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.UnsupportedEncodingException;
import java.nio.charset.StandardCharsets;
import java.security.GeneralSecurityException;
import java.security.SecureRandom;
import java.util.Base64;
import javax.crypto.Cipher;
import javax.crypto.spec.GCMParameterSpec;
import javax.crypto.spec.SecretKeySpec;

public class HuaweiEncoding {
    public static final String CHARSET_NAME = "UTF-8";
    public static final String EXCEPTION = "exception";

    public static final int IV_LENGTH = 16;
    private static final int GCM_TAG_LENGTH = 128;

    private static final Logger LOGGER = LoggerFactory.getLogger(HuaweiEncoding.class);
    private static String AES = "秘钥"; 可以上网找
    https://www.imaegoo.com/2020/aes-key-generator/128-bit

    public static void main(String[] args) {
        String encrypt = encrypt("8ffef99b85d64a768240be3fa23cf509b3285e54346e4e4292b31079c3720fb4");
        System.out.println("加密后:" + encrypt);
        String decrypt = decrypt(encrypt);
        System.out.println("解密后:" + decrypt);
    }

    /**
     * 解密字符串
     *
     * @param text 输入字符串
     * @return 解密字符串
     */
    public static String decrypt(String text) {
        try {
            byte[] data = Base64.getDecoder().decode(text);
            byte[] decoded = decryptByGcm(data, AES);

            return new String(decoded, CHARSET_NAME);

        } catch (GeneralSecurityException | UnsupportedEncodingException exception) {
            LOGGER.error(EXCEPTION, exception);
        }
        return "";
    }

    private static byte[] decryptByGcm(byte[] input, String key) throws GeneralSecurityException {
        byte[] initVector = new byte[IV_LENGTH];
        System.arraycopy(input, 0, initVector, 0, IV_LENGTH);
        final Cipher gcmCipher = createGCM(key, initVector, Cipher.DECRYPT_MODE);
        byte[] encrypted = new byte[input.length - IV_LENGTH];
        System.arraycopy(input, IV_LENGTH, encrypted, 0, encrypted.length);
        return gcmCipher.doFinal(encrypted);
    }

    private static Cipher createGCM(String key, byte[] initVector, int mode) throws GeneralSecurityException {
        Cipher gcmCipher = Cipher.getInstance("AES/GCM/NoPadding");
        gcmCipher.init(mode, getKey(key), new GCMParameterSpec(GCM_TAG_LENGTH, initVector));
        return gcmCipher;
    }

    private static SecretKeySpec getKey(String myKey) {
        int plus = 16 - myKey.trim().length();
        byte[] data = myKey.trim().getBytes(StandardCharsets.UTF_8);
        byte[] raw = new byte[16];
        byte[] plusByte = {
            0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f
        };
        for (int i = 0; i < 16; i++) {
            raw[i] = i < data.length ? data[i] : plusByte[plus];
        }
        return new SecretKeySpec(raw, "AES");
    }

    /**
     * 加密字符串
     *
     * @param text 输入字符串
     * @return 加密字符串
     */
    public static String encrypt(String text) {
        try {
            byte[] data = text.getBytes(CHARSET_NAME);
            byte[] encoded = encryptByGcm(data, AES);
            Base64.Encoder encoder = Base64.getEncoder();
            return encoder.encodeToString(encoded);

        } catch (UnsupportedEncodingException | GeneralSecurityException exception) {
            LOGGER.error(EXCEPTION, exception);
        }
        return "";
    }

    private static byte[] encryptByGcm(byte[] input, String key) throws GeneralSecurityException {
        byte[] initVector = generateSecureBytes(IV_LENGTH);
        Cipher gcmCipher = createGCM(key, initVector, Cipher.ENCRYPT_MODE);
        byte[] encrypted = gcmCipher.doFinal(input);
        byte[] data = new byte[IV_LENGTH + encrypted.length];
        System.arraycopy(initVector, 0, data, 0, IV_LENGTH);
        System.arraycopy(encrypted, 0, data, IV_LENGTH, encrypted.length);
        return data;
    }

    private static byte[] generateSecureBytes(int num) {
        byte[] bytes = new byte[num];
        new SecureRandom().nextBytes(bytes);
        return bytes;
    }
}

yml VS properties

https://www.jianshu.com/p/941aee2a99cf

内容格式比较:
.yml文件,通过:来分层,结构上,有比较明显的层次感,最后key赋值的:后需要留一个空格
.properties文件,通过.来连接,通过=来赋值

2.执行顺序
如果工程中同时存在application.properties文件和 application.yml文件,yml文件会先加载,
后加载的properties文件会覆盖yml文件。所以建议工程中,只使用其中一种类型的文件即可

jvm参数不生效 解决

添加一下注解,该类成为启动类

@SpringBootApplication(exclude = {FlywayAutoConfiguration.class})
@ComponentScan({"com.huawei", "com.huawei.it"})
@MapperScan("com.huawei.onebox.bookmarks.dao")

否则:

Tomcat 启动顺序

1 加载配置文件,如 server.xml 文件
2 初始化服务器,创建并配置 Connector、Engine、Host 等对象
3 启动并初始化所有的插件,如 Valve
4 启动所有的应用程序,从配置文件中加载上下文配置和应用程序部署信息
5 启动完成,开始处理客户端请求

启动jar包 主清单属性

https://blog.csdn.net/qq_18769269/article/details/83095012
添加:

            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <configuration>
                    <source>1.8</source>
                    <target>1.8</target>
                </configuration>
            </plugin>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <executions>
                    <execution>
                        <goals>
                            <goal>repackage</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>

java-jar jar包带环境变量(参数)启动

https://blog.csdn.net/zhaozhao121a/article/details/122232333
https://blog.csdn.net/zhaozhao121a/article/details/122232333
https://www.jianshu.com/p/fed7a174bfb8

java -Dservice_authentication_url=http://apicenter-kwe-beta.huawei.com/umws4login/services/Authentication -Dapplication_appId=com.huawei.officeit.2e.bookmark -Dapplication_appName=bookmark -Ddocker_version=1.0 -Ddocker_region=kwe -Ddocker_env=kwe_dev -Dconfigcenter_url=http://appconfig-beta.huawei.com/ConfigCenter/services/ConfigCenterService -Dsub_app_id=ms-bookmarks -Dhwenvironment=uat -Dsgov.secret=20~A2~254A0CB5710D3863BB800DFE16360B163FF83E410804F65F28D09640CCA0FACB~C37F97E155636CB4BF046A416A09FD527AC787066CB42B910C5D06C85F595342142AA1AF94725843291B89DE890CDE93FE7CBB68C7CCBF8AAD8F5F9A423D3C4C768B87F98D03563499393B6E9505A088~DE5990B48C05F4693D0A69FDBC0D581EA4F317C4A16F3AAD0A1BE3C35BB00F47 -Dconfigcenter.config_parts=0e50896c4c27452e88b5c55f7d13fa07,5d548f011f00469da488b8a4589fe219 -Dconfigcenter.work_key_cipher=20~A2~5B5CD51FE5CF7A36C0BC57942F215031E088428F07C25FF204EC9E2393945C66~D42E63F1E6E3D6A85164E0ACA6404814D8491EAD9CF26A586753CE9FDB24C05A91A3C30B9FCDADD36F13DECE05B97EC9~96D856590F128486B3BD81DD40D8C9B8047D8B3EBA53B8824894B0910767B444 -jar ms-bookmarks.jar

带jvm参数启动jar包

java  -Xms512m -Xmx512m  -jar jar包名

指定jdk1.8启动jar包

"C:\Program Files (x86)\Java\jre1.8.0_60\bin\java.exe" -jar jar包名

接口交互

HTTP 是短连接,每次请求获取完数据后就断开了,如果有多个用户访问,我们无法区分哪些调用是A用户的,哪些是B用户的,以及之前调用过什么接口 = http 连接是无状态的
为了解决这个问题,就有了 Token、Session、Cookie 这三个东西。

会话:确认用户状态

cookie VS token(session)

https://easydoc.net/a/token-session/

为了区分每个用户,或者说记住他们的状态,我们可以在服务端创建一块空间(创建 Session 对象)

Cookie:客户端存储机制之一
作用是在用户访问网站时,将一些数据存储在本地浏览器中,以便下次访问该网站时能够获取这些数据。
服务器通过HTTP响应头将cookie发送给浏览器,浏览器会将cookie保存在本地
每次请求该网站时,浏览器会自动将相关cookie发送给服务器,以便服务器识别用户身份和存取相关数据(如用户名、购物车、session id)。
cookie仅能存储文本格式数据,且存在安全问题(明文)。因此,开发者需谨慎使用cookie机制来存储敏感信息,如密码。
HTTP响应报文中包含一个Set-Cookie头部字段 = cookie → cookies由服务端产生

Token = 令牌:服务器-side session管理机制,原理类似于cookie
当用户进行登录等操作时,服务器会为用户生成唯一的Token,并将该Token发送给客户端,通常是以Cookie或者HTTP表头的形式发送。
客户端每次请求服务器时,会将该Token发送给服务器,服务器接收到Token后会对其进行验证,如果验证成功,就会认为当前用户已经登录,并且开启一个新的session,继而保存与该session相关的信息(例如用户订单等)。
Token机制相对于cookie机制来说,能够更好地保护用户隐私,并且不存在安全问题

Token 到底长什么样
eyJhbGciOiJIUzI1NiI.eyJzaWduVHMiOjE2MjM3MMwODEwfQ.s_CFOkQSmTLHUKLKJkjsdal
这是一段经过加密后的 Token,里面包含了 userid 等信息(可以自定义需要包含的数据)

cookie不能加密,是明文
token可以加密

Cookie:存储用户身份认证信息、用户偏好设置、购物车等临时性数据、跟踪用户行为和统计分析相关的信息

获取 cookies:

http VS https

http = HyperText Transfer Protocol 超文本传输协议

https = Hyper Text Transfer Protocol Secure 超文本传输安全协议
采用SSL(Secure Sockets Layer) 或 TLS(Transport Layer Security)协议 来加密HTTP传输的数据

SSL证书:在Web服务器 客户端浏览器之间建立加密链接的数字证书

在这里插入图片描述

RASP

RASP = Runtime Application Self Protection 应用运行时防护服务
通过模拟攻击 来测试Web应用程序的安全性,并提供详细的报告和建议
Rasp可以检测常见的Web应用程序漏洞,如SQL注入、跨站点脚本攻击(XSS)、跨站点请求伪造(CSRF)

CSRF = Cross-Site Request Forgery)
是一种网络攻击方式,攻击者通过伪造用户的请求,让用户在不知情的情况下执行恶意操作

防止CSRF攻击的办法:
1 验证请求来源:在服务器端对请求来源进行验证,只接受来自合法来源的请求
2. 添加随机令牌:在每个表单中添加一个随机生成的令牌,每次提交表单时都要验证该令牌的有效性
3. 使用验证码:在关键操作前,要求用户输入验证码,以确保用户是真实的
4. 限制敏感操作:修改密码、删除数据等,要求用户进行二次确认,以避免误操作
5. 及时更新软件

SSLException: Connection reset

https://blog.csdn.net/qq_40893824/article/details/133092514

http 2 检查

curl -I --http2 -s 接口

k8s

https://blog.csdn.net/qq_40893824/article/details/128632652

idea 打jar包

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.7.7</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.example</groupId>
    <artifactId>demo1</artifactId>
    <version>0.0.1</version>
    <name>demo1</name>
    <packaging>jar</packaging>

https://blog.csdn.net/weixin_43671437/article/details/102736236

jar执行

cmd 进入jar所在目录
java -jar jar包名

jar 文件路径

jar 文件路径 会找不到内部的相对路径
把jar当做一个文件,把txt文件和jar包放在同一目录里面
File file = new File("./data.xls"); 即可

linix 命令

https://www.huoban.com/news/post/5151.html

vi编辑器中

:wq:保存退出
:wq!:强制保存退出
:x:保存退出
:q:vim中表示退出
:q!:强制不保存退出,不对文件进行保存

看日志

https://cloud.tencent.com/developer/article/1579977

操作系统

cpu参数 4C8T8G
4C = 4核 core
8T = 8线程
8G = 内存

名词

BS CS架构

https://cloud.tencent.com/developer/article/2148508
bs:Browser/Server(浏览器/服务器)
cs:Client/Server(客户机/服务器)

容器

https://juejin.cn/post/7035957114396753951

nginx

https://zhuanlan.zhihu.com/p/34943332

数据埋点:

https://blog.csdn.net/qq_32727095/article/details/127700111
https://blog.csdn.net/qq_27924553/article/details/122415184

saas

https://www.woshipm.com/pmd/3631262.html

uc

统一沟通 (Unified Communications = UC)
http://ee.mweda.com/ask/279107.html
https://www.microsoft.com/zh-cn/microsoft-365/skype-for-business/server-hybrid

后门程序

后门程序:指绕过安全性控制 而获取对程序或系统访问权的程序方法。
在软件的开发阶段,程序员常常会在软件内创建后门程序
后门程序 可以修改程序设计中的缺陷。
但是,如果这些后门被其他人知道,或 在发布软件之前没有删除后门程序,那么它就成了安全风险,容易被黑客当成漏洞进行攻击

例子:
我写了一个数据迁移公共的web项目,通过postman调用接口,启动数据迁移的功能,这就是后门程序
解决办法:jar 包启动

UML 建模

https://www.zhihu.com/question/22129281
包图 - 基本架构组织,分层
类图 - 核心对象、接口,依赖关系
交互图 = 顺序图 - 执行流程,消息走向,调用关系
活动图(加强版流程图) - 核心算法,任务流程
状态图

安全

https://www.google.com.hk/search?client=aff-cs-360se&ie=UTF-8&q=%E6%B3%A8%E5%85%A5%E6%94%BB%E5%87%BB&oq=%E6%B3%A8%E5%85%A5%E6%94%BB%E5%87%BB&aqs=chrome…69i57l4.1236j0j1

https://zhuanlan.zhihu.com/p/409379105

ak sk

https://blog.csdn.net/Hongyu_Liu/article/details/118732960
证明你有某权限
身份 = 权限

AK:Access Key Id,用于标示用户
SK:Secret Access Key,用户用于加密认证字符串、用来验证认证字符串的密钥,SK必须保密
Access Key Id + Secret Access Key加密的方法来验证某个请求的发送者身份

公钥 私钥

https://help.aliyun.com/document_detail/42216.html

加密算法得到的一个密钥对:1个公钥、1个私钥(世界范围内唯一)

用其中一个密钥加密一段数据,只能使用密钥对中的另一个密钥才能解密数据

公钥可对会话进行加密、验证数字签名
只有使用对应的私钥才能解密会话数据

公钥是密钥对外公开的部分
私钥是非公开

SSL证书

SSL证书采用公钥体制

密钥仅为本人所有,可以产生其他人无法生成的加密文件,也就是形成了数字签名

SSL证书是一个经证书授权中心(CA)数字签名的、包含公开密钥拥有者信息、公开密钥的文件

请求鉴权

签名算法
系统鉴权
企业鉴权
应用鉴权
应用账户鉴权
用户token鉴权
外链用户鉴权

SHA256加密算法

https://blog.csdn.net/u011583927/article/details/80905740

横向越权 vs 纵向越权

https://blog.51cto.com/u_12295205/3161360
横向越权:攻击者尝试访问与他拥有相同权限的用户的资源
纵向越权:低级别攻击者尝试访问高级别用户的资源

RPC

RPC协议 远程过程调用(Remote Procedure Call)
它使得在不同计算机上的程序之间可以像调用本地函数一样调用远程函数,程序员可以编写像本地函数一样简单的代码,并且不需要了解底层网络传输的细节。
RPC协议通常使用TCP/IP或UDP协议进行数据传输

现代化互联网公司业务逐渐扩大,服务逐渐细分,很多服务之间需要通过远程分布式接口调用通讯,
不同的服务不是部署在同一个服务器上,比如订单服务在 A 服务上,付款服务在另一个服务上,有同步调用、也有异步调用,这个时候我们就需要远程调用不同的服务,使用的时候调用远程服务就像调用本地服务一样,引入一个 jar 包,就能通过 this.xxx() 一样调用远程服务,这背后的机制就是通过 RPC 技术

好文:
https://blog.csdn.net/qq_34272760/article/details/120734068

注入攻击

SQL注入、XSS(跨站脚本攻击)

注入攻击的本质,把用户输入的数据当做代码执行。
这里有2个关键条件,
第1个是用户能够控制输入;
第2个是原本程序要执行的代码,拼接了用户输入的数据。

解决注入攻击的核心思想:数据与代码分离

其他

图片渐进式加载

https://juejin.cn/post/7033780851053690894

burpsuite

是web代理拦截工具
https://t0data.gitbooks.io/burpsuite/content/chapter8.html

在这里插入图片描述

破解字典


电脑操作

网址分享怎么自动定位到中间

https://blog.csdn.net/qq_40893824/article/details/106441068#253__443
网址后面加上 #xxxx(id)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

qq_1403034144

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值