主要思想:
前后端分离项目,因为前端一个端口,后端一个端口,在后端代码中集成CAS点单登录的时候,需要解决前后端重定向的问题。通俗的来讲就是,在打开你前端页面的时候,如果没登录,要跳转到登录页面,登录成功后,再重定向到你的前端页面。如果这个问题解决了,证明你的单点登录也就基本上说成功了。
本文介绍单点登录实现主要分为3部分:
1.CAS服务器的配置
2.后端集成CAS
3.前端怎么处理重定向,与退出功能
1.CAS服务器的配置
①、下载CAS服务器和tomcat
特别声明:使用的tomcat要与自己的JDK版本一致,别出现JDK是32位,tomcat是64位的情况
②、HTTPS搭建
1、生成秘钥库
我们这里采用JDK自带的工具生成秘钥库。为了方便记,我这里所有口令均输入123456. 其他信息均输入guoxin.cn 。
keytool -genkey -alias itcast -keyalg RSA -keystore D:/workspace/cas/keystory/guoxin
输入密钥库口令:123456
再次输入新口令:123456
您的名字与姓氏是什么?
[Unknown]: guoxin.cn
您的组织单位名称是什么?
[Unknown]: guoxin.cn
您的组织名称是什么?
[Unknown]: guoxin.cn
您所在的城市或区域名称是什么?
[Unknown]: guoxin.cn
您所在的省/市/自治区名称是什么?
[Unknown]: sx
该单位的双字母国家/地区代码是什么?
[Unknown]: ty
CN=itcast.cn, OU=itcast.cn, O=itcast.cn, L=itcast.cn, ST=gd, C=zh是否正确?
[否]: y
输入 <itcast> 的密钥口令123456
(如果和密钥库口令相同, 按回车):
再次输入新口令:123456
2、 导出证书
刚才把秘钥库生成了,紧接着依据秘钥库导出证书。
C:\Users\Administrator>keytool -export -trustcacerts -alias itcast -file D:/workspace/cas/keystory/guoxin.cer -keystore D:/workspace/cas/keystory/guoxin
输入密钥库口令:123456
存储在文件 <D:/workspace/cas/keystory/guoxin.cer> 中的证书
C:\Users\Administrator>
3.将证书导入到JDK证书库
C:\Users\Administrator>keytool -import -trustcacerts -alias guoxin -file D:/workspace/cas/keystory/guoxin.cer -keystore "C:/Program Files/Java/jdk1.8.0_91/jre/lib/security/cacerts"
输入密钥库口令:
所有者: CN=itcast.cn, OU=itcast.cn, O=itcast.cn, L=sz, ST=gd, C=zh
发布者: CN=itcast.cn, OU=itcast.cn, O=itcast.cn, L=sz, ST=gd, C=zh
序列号: 5714b941
有效期开始日期: Wed Mar 21 14:44:00 CST 2018, 截止日期: Tue Jun 19 14:44:00 CST 2018
证书指纹:
MD5: 33:4E:86:6A:91:17:4B:7E:82:26:8F:FD:09:34:EF:CF
SHA1: CD:EE:46:D3:E7:04:E0:44:23:28:BF:81:84:53:57:0C:DC:59:D3:37
SHA256: E7:A1:C6:66:02:A1:C5:0F:EA:23:E5:C1:06:55:8E:00:71:6D:E9:E5:21:73:9B:C6:BE:C6:69:71:7A:B8:86:3B
签名算法名称: SHA256withRSA
版本: 3
扩展:
#1: ObjectId: 2.5.29.14 Criticality=false
SubjectKeyIdentifier [
KeyIdentifier [
0000: 72 10 76 0A 97 97 5F 90 64 D4 85 2E 81 0E DF A7 r.v..._.d.......
0010: 8C 1E EE 83 ....
]
]
是否信任此证书? [否]: y
证书已添加到密钥库中
C:\Users\Administrator>
特别声明:注意修改JDK证的位置,以你的JDK位置所在为标准
③、tomcat发布CAS服务端项目
-
解压一个tomcat,放到D:\workspace\cas\目录下,把刚才我们下载的cas解压打开target目录下有个cas.war 拷贝到tomcat的webapps目录并解压,删除war包。
-
下载的cas解压目录下还有一个文件target\war\work\org.jasig.cas\cas-server-webapp\WEB-INF\cas.properties,把他拷贝到webapps\cas\WEB-INF目录下。
-
修改spring-configuration\propertyFileConfigurer.xml,把location=“file:/etc/cas/cas.properties”换成刚才cas.properties的绝对路径。
<util:properties id=“casProperties” location=“file:D:/workspace/cas/apache-tomcat-8.5.16/webapps/cas/WEB-INF/cas.properties” />
-
修改tomcat的conf/server.xml,加入如下代码
<Connector port="443" protocol="org.apache.coyote.http11.Http11NioProtocol"
maxThreads="150" SSLEnabled="true" scheme="https" secure="true"
clientAuth="false" sslProtocol="TLS"
keystoreFile="D:\workspace\cas\keystory\guoxin"
keystorePass="123456" />
启动tomcat
访问https://localhost 出现如tomcat界面说明大功告成!
2.后端集成CAS
请查看以下连接:
springboot集成CAS单点登录客户端_今朝花落悲颜色的博客-CSDN博客_springboot集成cas单点登录
3.前端怎么处理重定向,与退出功能
后端集成CAS单点登录后,前端访问后端,如果不进行单点登录,就像有道门挡在他们中间。如何打开门后,再返回前端界面?
我是这样的构思:前端先去获取从后端哪里获取用户名,倘若没进行单点登录,就不会获取到用户名,这时延时个0.4S,前端重定向到后端的一个接口,这时会进行CAS单点登录,登录成功后,访问的这个后端接口又重定向到前端,这样就完成了单点登录并返回到前端界面。
前端代码:
在ant desigen pro中修改layout文件夹下的SecurityLayout.tsx的代码:
import React from 'react';
import { connect, ConnectProps } from 'umi';
import { ConnectState } from '@/models/connect';
import { CurrentUser } from '@/models/user';
import axios from 'axios';
import defaultSettings from '../../config/defaultSettings';
import proPath from '../../public/path';
// import {getSeesion,getUserId} from '@/utils/utils'
interface SecurityLayoutProps extends ConnectProps {
loading?: boolean;
currentUser?: CurrentUser;
}
interface SecurityLayoutState {
isReady: boolean;
casUser: string;
}
var currentCasUser: string;
class SecurityLayout extends React.Component<SecurityLayoutProps, SecurityLayoutState> {
state: SecurityLayoutState = {
isReady: false,
casUser: '',
};
componentDidMount() {
axios.get("guoxin/Caslogin/getCasName")
.then(response => {
defaultSettings.currentUser=response.data;
currentCasUser = response.data;
// console.log("cas用户名:", response);
this.setState({
casUser: response.data,
})
})
this.setState({
isReady: false,
});
}
render() {
setTimeout(() => {
// console.log("延时器运行!");
if (this.state.casUser.length == 0) {
window.location.href ='http://localhost:8081/hello'//后端重定向前端的接口
}
}, 400)
// console.log("用户:", defaultSettings.currentUser);
const { children, loading, currentUser } = this.props;
// 你可以把它替换成你自己的登录认证规则(比如判断 token 是否存在)
// console.log("用户名:", currentCasUser);
// if (flag ==1) {
// if (this.state.casUser.length>0) {
// flag += 1
// window.location.href = "http://localhost:8000"
// }
// }
// if ((!isLogin && loading) || !isReady) {
// return <PageLoading />;
// }
// if (!isLogin && window.location.pathname !== '/user/login') {
// return <Redirect to={`/user/login?${queryString}`} />;
// }
return children;
}
}
export default SecurityLayout;
后端代码:
①获取用户名:
@ApiOperation(value = "获取cas登录用户名", notes = "获取cas登录用户名")
@GetMapping("/getCasName")
public String getCasName(HttpServletRequest request, HttpServletResponse response){
Assertion assertion=(Assertion) request.getSession().getAttribute(AbstractCasFilter.CONST_CAS_ASSERTION);
if (assertion!=null){
String username=new String(Base64.getDecoder().decode(assertion.getPrincipal().getName()));
System.out.println("登录的用户名:"+username);
return username;
}else return null;
}
②登录成功后会回调该方法
//进入系统首页方法,如果没有登录,会跳转到CAS统一登录页面,登录成功后会回调该方法。
@RequestMapping("/hello")
public String index(HttpServletRequest request,HttpServletResponse response){
Assertion assertion=(Assertion) request.getSession().getAttribute(AbstractCasFilter.CONST_CAS_ASSERTION);
System.out.println("登录用户名1:"+assertion.getPrincipal().getName());
response.setHeader("Access-Control-Allow-Origin",WEB_URL);
return "redirect:http://localhost:8256";//前端地址
}