1、MD5&盐值&BCrypt

MD5 (Message Digest algorithm 5,信息摘要算法)

1、压缩性:任意长度的数据,算出的MD5值长度都是固定的。

2、容易计算:从原数据计算出MD5值很容易。

3、抗修改性:对原数据进行任何改动,哪怕只修改1个字节,所得到的MD5值都有很大区别。

4、强抗碰撞:想找到两个不同的数据,使它们具有相同的MD5值,是非常困难的。

5、不可逆

加盐:

1、通过生成随机数与MD5生成字符串进行组合

2、数据库同时存储MD5值与salt值。验证正确性时使用salt进行MD5

1
2
3
+ Spring的加密
+ 自动加盐
+ match匹配(与encode匹配)

2、分布式session共享

问题:

不同服务session不共享

同一服务session不同步

session原理

image-20220218001900202

分布式session解决方案

1、session复制

image-20220218002213539

Session复制(tomcat之间同步)

1
2
3
4
5
6
+ 优点:
+ web-server(Tomcat)原生支持,只需要修改配置文件
+ 缺点:
+ session同步需要数据传输,占用大量网络带宽,降低了服务器群的业务处理能力
+ 任意一台web-server保存的数据都是所有web-server的session总和,受到内存限制无法水平扩展更多的web-server
+ 大型分布式集群情况下,由于所有web-server都全量保存数据,所以此方案不可取。

2、客户端存储

image-20220218002226115

放到cookie中

1
2
3
4
5
6
7
8
+ 优点
+ 服务器不需存储session,用户保存自己的session信息到cookie中。
+ 节省服务端资源
+ 缺点
+ 都是缺点,这只是一种思路。
+ 每次http请求,携带用户在cookie中的完整信息,浪费网络带宽
+ session数据放在cookie中,cookie有长度限制4K,不能保存大量信息
+ session数据放在cookie中,存在泄漏、篡改、窃取等安全隐患

3、hash一致性

image-20220218002507539

Hash一致性(修改负载均衡)

+ 服务器闪断会丢失

+ 服务器数量变化重新hash,部分会丢失

1
2
3
4
5
6
7
8
9
10
+ 优点:
+ 只需要改nginx配置,不需要修改应用代码 负载均衡,只要hash属性的值分布是均匀的,多台web-server的负载是均衡的
+ 可以支持web-server水平扩展(session同步法是不行的,受内存限制)
缺点
+ session还是存在web-server中的,所以web-server重
启可能导致部分session丢失,影响业务,如部分用户
需要重新登录
+ 如果web-server水平扩展,rehash后session重新分布,
也会有一部分用户路由不到正确的session
+ 但是以上缺点问题也不是很大,因为session本来都是有有

4、统一存储

image-20220218002612719

1
2
3
4
5
6
7
+ 优点:
+ 没有安全隐患
+ 可以水平扩展,数据库/缓存水平切分即可
+ web-server重启或者扩容都不会有 session丢失
+ 不足
+ 增加了一次网络调用,并且需要修改应 用代码;如将所有的getSession方法替换为从Redis查数据的方式。redis获取数 据比内存慢很多
+ 上面缺点可以用SpringSession完美解决

5、扩大cookie作用域

解决子域共享问题

问题:多域名

SpringSession

配置类:json编码、cooki子域问题

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
@Configuration
public class GulimallSessionConfig {
@Bean
public CookieSerializer cookieSerializer() {
DefaultCookieSerializer cookieSerializer = new DefaultCookieSerializer();
//放大作用域
cookieSerializer.setDomainName("gulimall.com");
cookieSerializer.setCookieName("GULISESSION");
return cookieSerializer;
}

@Bean
public RedisSerializer<Object> springSessionDefaultRedisSerializer() {
return new GenericJackson2JsonRedisSerializer();
}
}

原理:装饰者模式

狸猫换太子

@EnableRedisHttpSession 导入 RedisHttpSessionConfiguration 配置

1、给容器中添加了一个组件 RedisOperationsSessionRepository:Redis操作session,session的增删改查封装类;

2、继承 SpringHttpSessionConfiguration 初始化了一个 SessionRepositoryFilter:session 存储过滤器;每个请求过来都必须经过 Filter 组件;创建的时候,自动从容器中获取到了 SessionRepository;

SessionRepositoryFilter:

  • 将原生的 HttpServletRequest Response 包装成 SessionRepositoryRequestWrapper ResponseWrapper;包装后的对象应用到了后面整个执行链;
  • 以后获取 request.getSession(); 都会调用 wrappedRequesr.getSession(); 从SessionRepository获取;

3、装饰者模式

1
2
3
4
5
6
7
8
9
10
11
12
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
request.setAttribute(SESSION_REPOSITORY_ATTR, this.sessionRepository);
SessionRepositoryFilter<S>.SessionRepositoryRequestWrapper wrappedRequest = new SessionRepositoryFilter.SessionRepositoryRequestWrapper(request, response);
SessionRepositoryFilter.SessionRepositoryResponseWrapper wrappedResponse = new SessionRepositoryFilter.SessionRepositoryResponseWrapper(wrappedRequest, response);

try {
filterChain.doFilter(wrappedRequest, wrappedResponse);
} finally {
wrappedRequest.commitSession();
}

}

3、sso单点登录

跨域名单点登录简单实现:

1、服务端:未登录跳转认证中心(附带参数保存原地址)

2、认证中心:登录成功本地保存cookie(sso_token)

3、认证中心:保存登录用户登录状态到redis中

4、认证中心:重定向url中附带token跳转回原页面

5、服务端:根据token查询redis获取用户信息保存session

6、其他服务端:未登录跳转到认证中心,直接登录成功返回

服务端:根据有无session判断是否登录

认证中心:根据有无sso_token判断是否登录

可实现:filter、jwt、springsecurity

单点登录流程

4、ThreadLocal同一个线程共享数据

image-20220218004911488

1
2
3
4
5
6
7
public static ThreadLocal<UserInfoTo> toThreadLocal = new ThreadLocal<>();

// 赋值
toThreadLocal.set(userInfoTo);

// 取值
UserInfoTo userInfoTo = CartInterceptor.toThreadLocal.get();