昨天我们的文件上传Demo已经比较完善了,今天我们来学习单点登录,更加的完善它,那么什么是单点登录呢?
背景
传统的登录系统中,每个站点都实现了自己的专用登录模块。各站点的登录状态相互不认可,各站点需要逐一手工登录。这样的系统,我们又称之为多点登陆系统。应用起来相对繁琐(每次访问资源服务都需要重新登陆认证和授权)。与此同时,系统代码的重复也比较高。由此单点登陆系统诞生。
一、概述
百度百科:
通俗易懂:
单点登录SSO(Single Sign On)说得简单点就是在一个多系统共存的环境下,用户在一处登录后,就不用在其他系统中登录,也就是用户的一次登录能得到其他所有系统的信任。单点登录在大型网站里使用得非常频繁,例如像阿里巴巴这样的网站,在网站的背后是成百上千的子系统,用户一次操作或交易可能涉及到几十个子系统的协作,如果每个子系统都需要用户认证,不仅用户会疯掉,各子系统也会为这种重复认证授权的逻辑搞疯掉。实现单点登录说到底就是要解决如何产生和存储那个信任,再就是其他系统如何验证这个信任的有效性,因此要点也就以下两个:
- 存储信任
- 验证信任
二、实现
前面我们已经有了上传、网关、页面服务,接下来创建单点登录最重要的授权服务
1.添加pom依赖
web、oath2、nacosdiscovery、nacosconfig
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!--SSO技术方案:springSecurity+JWT+oauth2-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-oauth2</artifactId>
</dependency>
<!--nacos注册发现-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
</dependency>
2.构建配置文件
server:
port: 8071
spring:
application:
name: sca-auth
cloud:
nacos:
discovery:
server-addr: localhost:8848
config:
server-addr: localhost:8848
3.项目启动类
@SpringBootApplication
public class ResourceAuthApplication {
public static void main(String[] args) {
SpringApplication.run(ResourceAuthApplication.class, args);
}
}
4.启动项目
项目启动时生成一个密码(oauth2的作用)
访问我们配置的端口号出现如下界面
账号默认为user,密码就是项目启动时生成的密码,登录成功后会返回404,这表示登录成功,因为我们没有页面,这里我们可以自己配置一个页面,不过没啥必要
5.自定义登录
业务逻辑图:
我们在实现登录时,会在UI工程中,定义登录页面(login.html),然后在页面中输入自己的登陆账号,登陆密码,将请求提交给网关,然后网关将请求转发到auth工程,登陆成功和失败要返回json数据,在这个章节我们会按这个业务逐步进行实现。
定义安全配置类
修改SecurityConfig配置类,添加登录成功或失败的处理逻辑
/*1.配置加密对象
* 2.配置认证规则
* */
@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {
//初始化加密对象
//此对象提供了不可逆的加密方式,相对于MD5更加安全
@Bean
public BCryptPasswordEncoder passwordEncoder(){
return new BCryptPasswordEncoder();
}
//登录成功处理器
@Bean
public AuthenticationSuccessHandler successHandler(){
return (request,response,authentication) ->{
//1.构建map对象,封装响应数据
Map<String,Object> map=new HashMap<>();
map.put("state",200);
map.put("message","login ok");
//2.将map对象写到客户端
writeJsonToClient(response,map);
};
}
//登录失败处理器
@Bean
public AuthenticationFailureHandler failureHandler(){
return (request,response, exception)-> {
//1.构建map对象,封装响应数据
Map<String,Object> map=new HashMap<>();
map.put("state",500);
map.put("message","login failure");
//2.将map对象写到客户端
writeJsonToClient(response,map);
};
}
private void writeJsonToClient(HttpSe