1 单点登录
关于单点登录的原理,我觉得下面这位老哥讲的比较清楚,有兴趣可以看一下,下面我把其中的重点在此做个笔记总结
https://juejin.cn/post/6844904079274197005
主流的单点登录都是基于共享 cookie 来实现的
1.1 同域单点登录
适用场景:都是企业内部系统,所有系统都适用同一个一级域名,并通过不同的二级域名区分
举个例子:公司有一个一级域名cjs.com,我们有三个系统需要实现单点登录,分别是门户系统(sso.cjs.com)、应用系统1(app1.cjs.com)、应用系统2(app2.cjs.com)
核心原理:
1.2 跨域单点登录
由于域名不一样不能共享 Cookie 了,这样就需要通过一个单独的授权服务(UAA)来做统一登录,并基于共享UAA的 Cookie 来实现单点登录。
举个例子:公司接到一个大项目,把其中部分系统外包给第三方来做,或者直接采购第三方服务商的系统,或者是子业务系统1采购服务商A的系统,子系统2采购B服务商的系统。无论什么情况,总之系统集成就需要单点登录。
核心原理:
1.3 基于OAuth2的跨域单点登录
1.4 前后端分离的跨域单点登录
前后端分离的核心概念是后端仅返回前端所需的数据,不再渲染HTML页面,前端HTML页面通过AJAX调用后端的RESTFUL API接口并使用JSON数据进行交互
跨域间的前后端分离项目也是基于共享统一授权服务(UAA)的cookie来实现单点登录的,但是与非前后分离不一样的是存在以下问题需要解决
示例参考:
http://localhost:9000/callback.html?code=xxx
2 Spring Security OAuth 2.0迁移指南
从 Spring Security 5.2.x 开始,OAuth 2.0 Clients 和 Resource Servers 已经从 Security OAuth 2.x 迁移到 从 Spring Security,而且 Spring Security 不再提供 Authorization Server 的支持。
总之呢,Spring Security OAuth这个项目以后就处于维护状态了,不会再更新了,建议使用Spring Security
迁移以后,很多地方都不一样了,就我注意到的说下几点变化
首先,以前单点登录使用@EnableOAuth2Sso注解,现在推荐使用oauth2Login()方法
其次,授权服务器的写法不一样了
默认的端点都变成 /oauth2 开头了
更多变化可以阅读源码,亦可参见 OAuth 2.0 Features Matrix 查看二者支持的特性
3 @EnableOAuth2Sso的作用
@EnableOAuth2Sso: 标记服务作为一个OAuth 2.0客户端。这意味着它将负责将资源所有者(最终用户)重定向到授权服务器,在那里用户必须输入他们的凭据。完成后,用户被重定向回客户端,并携带授权码。然后,客户端获取授权码,并通过调用授权服务器以获取访问令牌。只有在此之后,客户端才能使用访问令牌调用资源服务器。
4 补充:根据pid递归查找子机构
package com.soa.supervision.gateway.service.impl;
import com.alibaba.fastjson.JSON;
import com.soa.supervision.gateway.entity.SysDept;
import com.soa.supervision.gateway.repository.SysDeptRepository;
import com.soa.supervision.gateway.service.SysDeptService;
import org.apache.commons.lang3.StringUtils;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;
/**
* 机构表 服务实现类
*
* @author ChengJianSheng
* @since 2022-03-08
*/
@Service
public class SysDeptServiceImpl implements SysDeptService {
private static final String CACHE_PREFIX = "DEPT:";
@Resource
private SysDeptRepository sysDeptRepository;
@Resource
private StringRedisTemplate stringRedisTemplate;
/**
* 递归 向下查找当前机构的所有子机构
*/
@Override
public List getAllByPid(Integer pid, List list) {
List subDeptIdList = sysDeptRepository.findIdByPid(pid);
if (CollectionUtils.isEmpty(subDeptIdList)) {
return new ArrayList<>();
} else {
list.addAll(subDeptIdList);
subDeptIdList.forEach(e->{
getAllByPid(e, list);
});
}
return list;
}
@Override
public String getSubDeptIdListByPid(Integer pid) {
String key = CACHE_PREFIX + pid;
String val = stringRedisTemplate.opsForValue().get(key);
if (StringUtils.isBlank(val)) {
synchronized (SysDept.class) {
if (StringUtils.isBlank(val)) {
List deptIds = getAllByPid(pid, new ArrayList<>());
deptIds.add(pid);
val = JSON.toJSONString(deptIds);
stringRedisTemplate.opsForValue().set(key, val, 1, TimeUnit.HOURS);
}
}
}
return val;
}
}
package com.soa.supervision.gateway.repository;
import com.soa.supervision.gateway.entity.SysDept;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;
import java.util.List;
/**
* @Author ChengJianSheng
* @Date 2022/3/8
*/
public interface SysDeptRepository extends JpaRepository {
@Query(value = "SELECT id FROM sys_dept WHERE pid = :pid", nativeQuery = true)
List findIdByPid(@Param("pid") Integer pid);
}
5 有用的文档
Spring Security相关
Spring Boot OAuth相关
手机扫一扫
移动阅读更方便
你可能感兴趣的文章