前言
这段时间断断续续学习了单点登录的相关知识,这里汇总一下,加深下记忆。
什么是单点登录
单点登录(Single Sign On,简称SSO) 是当前比较流行的一种用于企业业务整合的解决方案。
SSO并不具体指哪一种框架,而是一种思想。企业里,如果想让用户只登录一次,就可以访问所有互相信任的应用系统时,我们就可以采用SSO。
例如阿里下有淘宝网、天猫网、聚划算等网站。当我们在其中一个网站登录了,在同个浏览器访问其他的几个网站时,就无需再进行登录。
单点登录的时序图
以下根据我自己的理解画的两个时序图,来简单介绍下单点登录中,用户登录认证流程和用户注销流程。
用户登录认证流程:
用户注销流程:
什么是CAS
CAS(Cantral Authentication Service)是耶鲁大学发起的一个开源项目(github地址为https://github.com/apereo/cas),是单点登录的实现方式之一。
CAS分为CAS服务端和CAS客户端。
CAS服务端负责完成对用户的认证工作,CAS服务端需要独立部署。
CAS客户端集成到每个应用系统上。当用户需要在认证之后才能访问应用系统受保护资源时,应用系统判断该用户是否已认证,如果没有认证,则重定向到CAS服务端进行身份认证。
CAS协议能适配大多数语言编写的应用系统,因此应用十分广泛。
采用CAS实现单点登录
以下演示搭建CAS,基础环境为:JDK1.8、tomcat8.5、apache-maven-3.6.1。
修改hosts文件
由于是在本地搭建,因此我在hosts文件,添加以下三个域名,解析到172.0.0.1。方便后续区分是客户端还是服务端。
127.0.0.1 cas.server.com
127.0.0.1 cas.client.a.com
127.0.0.1 cas.client.b.com
搭建CAS服务端
1、从github上下载cas-overlay-template(地址:https://github.com/apereo/cas-overlay-template/tree/5.3),此处使用5.3版本。
2、使用maven命令打包(需要在本地安装Maven)。Windows下为.build.cmd package
,Linux下为./build.sh package
。打包后的war包在target目录下。
3、由于cas-server-webapp-tomcat-5.3.14.war很大,下载比较慢。可以直接到 http://oss.sonatype.org/
找到对应版本的war包。下载后放到本地Maven仓库的对应位置即可。
4、由于CAS默认使用的是基于https协议。部署CAS服务端时,需要添加证书,或者改为兼容使用http协议。这里为了方便,直接修改war包的配置文件,兼容使用http协议。
4.1 在cas.war部署包下找到WEB-INFclassesapplication.properties
添加:
cas.tgc.secure=false
cas.serviceRegistry.initFromJson=true
4.2 在cas.war部署包下找到WEB-INFclassesservicesHTTPSandIMAPS-10000001.json
,修改 serviceId 的值,添加http:
"serviceId" : "^(https|http|imaps)://.*",
5、在cas.war部署包下找到WEB-INFclassesapplication.properties
,将server.port修改为8080。
6、将修改后的cas.war包放到tomcat的webapps目录下,启动tomcat,在浏览器中输入http://localhost:8080/cas
,默认用户名:casuser
,默认密码:Mellon
。如果要修改密码,可以修改WEB-INFclassesapplication.properties
文件。
cas服务登录界面如下图:
配置CAS服务端数据库
上面是通过写在配置文件中的用户名和密码进行登录的,我们可以修改为从数据库中获取。
1、修改CAS项目的pox.xml,添加以下依赖。
<dependency>
<groupId>org.apereo.cas</groupId>
<artifactId>cas-server-support-jdbc-drivers</artifactId>
<version>${cas.version}</version>
</dependency>
<dependency>
<groupId>org.apereo.cas</groupId>
<artifactId>cas-server-support-jdbc</artifactId>
<version>${cas.version}</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.46</version>
</dependency>
2、根据搭建CAS服务端
章节,重新打包部署包。
3、修改在cas.war部署包下的WEB-INFclassesapplication.properties
文件。
3.1 注释掉默认的用户# cas.authn.accept.users=casuser::Mellon
。
3.2 添加以下内容,具体配置含义,可以到官方文档查看。
cas.authn.jdbc.query[0].url=jdbc:mysql://{mysql.IP}:3306/{db.name}?useUnicode=true&characterEncoding=utf-8
cas.authn.jdbc.query[0].user={username}
cas.authn.jdbc.query[0].password={password}
# 指定查询账号密码sql
cas.authn.jdbc.query[0].sql=select * from user where username=?
# 指定密码字段
cas.authn.jdbc.query[0].fieldPassword=password
# 数据库驱动
cas.authn.jdbc.query[0].driverClass=com.mysql.jdbc.Driver
#密码加密策略,如果密码字段没有加密,则这一段配置可以省略
# 默认加密策略
cas.authn.jdbc.query[0].passwordEncoder.type=DEFAULT
cas.authn.jdbc.query[0].passwordEncoder.characterEncoding=UTF-8
# 指定密码字段加密算法为MD5
cas.authn.jdbc.query[0].passwordEncoder.encodingAlgorithm=MD5
4、修改war包后,根据搭建CAS服务端
章节,重新部署。输入数据库中的账号和密码,即可成功登录。
搭建CAS客户端
本部分参考SpringBoot整合CAS单点登录 搭建。
搭建的客户端代码,存放在我的github仓库。
1、使用springboot,搭建web项目,项目名叫cas-client-A
,并且引入以下依赖。
<dependency>
<groupId>net.unicon.cas</groupId>
<artifactId>cas-client-autoconfig-support</artifactId>
<version>1.4.0-GA</version>
</dependency>
2、在启动类添加注解@EnableCasClient
。
3、在配置文件,添加以下配置。
cas.server-url-prefix=http://cas.server.com:8080/cas
cas.client-host-url=http://cas.client.a.com:9001
server.port=9001
# 填CAS服务器的登录地址
cas.server-login-url=http://cas.server.com:8080/cas/login
#自定义的退出url,退出成功后跳转路径
casClientLogoutUrl=http://cas.server.com:8080/cas/logout
4、添加过滤器,用于从请求中获取用户CAS登录信息,生成本地用户登录信息。
public class LocalUserInfoFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) {
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
HttpServletRequest request_ = (HttpServletRequest) request;
String loginName = getAccountNameFromCas(request_);
if (!StringUtils.isEmpty(loginName)) {
request_.getSession().setAttribute("loginName", loginName);
}
chain.doFilter(request, response);
}
@Override
public void destroy() {
}
/**
* 从cas中获取用户名
*
* @param request
* @return
*/
private static String getAccountNameFromCas(HttpServletRequest request) {
Assertion assertion = (Assertion) request.getSession().getAttribute(AbstractCasFilter.CONST_CAS_ASSERTION);
if (assertion != null) {
AttributePrincipal principal = assertion.getPrincipal();
return principal.getName();
} else return null;
}
}
5、添加cas配置类。
@Configuration
public class FilterConfig {
@Value("${cas.server-url-prefix}")
private String CAS_URL;
@Value("${cas.client-host-url}")
private String APP_URL;
/**
* 单点登录退出
*/
@Bean
public FilterRegistrationBean singleSignOutFilter() {
FilterRegistrationBean registrationBean = new FilterRegistrationBean();
registrationBean.setFilter(new SingleSignOutFilter());
registrationBean.addUrlPatterns("/*");
registrationBean.addInitParameter("casServerUrlPrefix", CAS_URL);
registrationBean.setName("CAS Single Sign Out Filter");
registrationBean.setOrder(1);
return registrationBean;
}
/**
* 从request中获取cas登录信息,根据登录信息获取当前用户,创建本地session
*/
@Bean
public FilterRegistrationBean registrationBean() {
FilterRegistrationBean registrationBean = new FilterRegistrationBean();
registrationBean.setFilter(new LocalUserInfoFilter());
registrationBean.addUrlPatterns("/*");
registrationBean.setName("localUserInfoFilter");
registrationBean.setOrder(2);
return registrationBean;
}
}
6、添加controller。当用户登录后,访问/
,返回当前系统的端口号。当用户访问/logout
,调用cas服务端注销URL,注销登录。
@RestController
public class TestController {
@Value("${server.port}")
private String serverPort;
@Value("${casClientLogoutUrl}")
private String clientLogoutUrl;
@GetMapping("/")
public String hello() {
return "我是VIP:" + serverPort;
}
@GetMapping("/logout")
public void logout(HttpSession session, HttpServletResponse response)throws Exception {
session.invalidate();//销毁session
//使用cas退出成功后,跳转页面
response.sendRedirect(clientLogoutUrl);
}
}
7、根据步骤1-7,创建cas-client-B项目,项目配置文件的 cas.client-host-url
和 server.port
修改为下面两个值。
cas.client-host-url=http://cas.client.b.com:9002
server.port=9002
测试CAS
1、启动CAS服务端。
2、启动两个CAS客户端。
测试登录
1、在浏览器初次访问cas.client.a.com
时,会跳转到cas登录页面。
2、输入用户登录信息,登录cas。
3、登录成功后,就能正确访问cas.client.a.com
了。
4、在浏览器访问cas.client.b.com
,此时不需要登录,也能正常访问。
测试注销
1、访问cas.client.a.com/logout
注销登录,此时页面会跳转到cas注销成功页面。
2、刷新cas.client.b.com
页面,此时会跳转到cas登录页面,证明cas注销成功。