cookie与session与token、普通登录、单点登录、三种常见实现方式、cas-server、cas-client
注:oauth2 是保护服务端资源,即受 oauth2 保护的资源能不能被客户端访问;cas 是保护用户信息,即该用户有没有权限访问 cas 客户端的资源。oauth2 已经停止维护,被 spring authorization server 代替。
token 是由服务端通过用户唯一标识、时间戳、签名等信息再经过加密算法加密生成的字符串,其是存储在客户端的,也就是无状态的。一般分为 access_token 和 refresh_token。微信授权登录小程序、其它 app、网站等就是 token 最成熟的使用例子。
普通登录一般分为两种,即基于 cookie 的和基于 token 的。
基于 cookie 的是指用户登录后,服务端会将用户信息存储到 session 中,然后将 sessionId 设置到响应头的 set-cookie 中,客户端每次请求时都携带 cookie,服务端接受到请求后根据其携带的 sessionId 获取对应用户信息进行权限校验等。spring security、shiro 等认证授权框架的默认实现就是基于 cookie 的。
基于 token 的是指用户登录后,服务端根据用户信息生成 token 同时将 token 返回给客户端,客户端将其存储,后续请求中都携带 token,服务端在收到请求后先校验 token,再做后续处理。
单点登录(Single Sign On),简称 SSO,是比较流行的企业业务整合的解决方案之一,SSO 的定义是在多个应用系统中,用户只需要登录一次就可以访问所有相互信任的应用系统。(摘自百度百科)。
单点登录的本质是实现用户登录状态再多个应用间的共享。在普通登录中用户登录状态是存储在 session 或 token 中的,那么要实现单点登录就要实现 session 或 token 的共享。
单点登录最常用的三种实现方式是父域 cookie、认证中心、localstorage。
父域 cookie 指的是将服务端返回的 sessionId 设置到父域名的 cookie 中,也就是将 domain 属性设置为父域名,将 path 属性设置为根路径,这样,该父域名下的所有字域名都可以访问该 cookie 。
认证中心,顾名思义,就是专门进行认证的应用系统。
下图为常用认证中心 cas 的工作原理。
localstorage 属于浏览器技术,用户成功后将 session 或 token 保存到浏览器的 localstorgae 中,然后通过前端技术 iframe + postMessage() 将 session 或 token 发送到其它需要相互信任的应用系统对应的域下的 localstorgae,这样就实现了登录信息的共享,每次请求时都从 localstorage 取到 session 或 token。然后进行授权等操作。
简单说下 cas server 的搭建。
为了便于开发者进行自定义开发及扩展,cas 提供了覆盖模版 cas-overlay-template,开发者可以通过覆盖文件及增加的方式对其进行自定义化和扩展。
github cas-overlay-template github 上有 cas 各个版本的 overlay-template,可按需进行下载。(cas 6.0 之前的版本基于 jdk8,采用 maven 管理依赖,cas 6.0 及之后的版本基于 jdk11,采用 gradle 管理依赖)。
得到源码之后有三种处理方式:
此时,我们可以对 cas server 进行自定义开发和扩展,如是否使用 https、配置数据库、自定义密码加密,自定义登录页面等。(以下示例基于 cas-5.3.16)
支持 http:
overlays/org.apereo.cas.cas-server-webapp-tomcat-x.x.x/WEB-INF/classes/services 目录下的 HTTPSandIMAPS-10000001.json 拷贝到 resources/services 目录下,增加 http 支持。同时,若需要使用 https,则需要生成 idk 证书,具体请请教度娘。
{
"@class" : "org.apereo.cas.services.RegexRegisteredService",
"serviceId" : "^(https|http|imaps)://.*", // 修改这里
"name" : "HTTPS and IMAPS",
"id" : 10000001,
"description" : "This service definition authorizes all application urls that support HTTPS and IMAPS protocols.",
"evaluationOrder" : 10000
}
配置数据库:
pom.xml 文件中加入依赖 :
<dependency>
<groupId>org.apereo.casgroupId>
<artifactId>cas-server-support-jdbcartifactId>
<version>${cas.version}version>
dependency>
<dependency>
<groupId>org.apereo.casgroupId>
<artifactId>cas-server-support-jdbc-driversartifactId>
<version>${cas.version}version>
dependency>
<dependency>
<groupId>mysqlgroupId>
<artifactId>mysql-connector-javaartifactId>
<version>8.0.16version>
dependency>
application.properties 文件中加入一下配置:
# authentication
cas.authn.jdbc.query[0].driverClass=com.mysql.cj.jdbc.Driver
cas.authn.jdbc.query[0].url=jdbc:mysql://ip:3306/database-name?useUnicode=true&characterEncoding=utf8&useSSL=false&&serverTimezone=UTC
cas.authn.jdbc.query[0].user=root
cas.authn.jdbc.query[0].password=******
cas.authn.jdbc.query[0].sql=select * from user where username = ?
cas.authn.jdbc.query[0].fieldPassword=password
总而言之,自定义就是将 overlays/org.apereo.cas.cas-server-webapp-tomcat-x.x.x/WEB-INF/classes 目录下的某个文件拷贝 到 resources 目录下,然后进行修改,这就是覆盖。大致项目结构如下:
# cas server
server.context-path=/cas-sso-server
server.port=9625
# ssl
server.ssl.enabled=false
server.ssl.key-store=classpath:cas-jdk8
server.ssl.key-store-password=962464
server.ssl.key-password=962464
# authentication
cas.authn.jdbc.query[0].driverClass=com.mysql.cj.jdbc.Driver
cas.authn.jdbc.query[0].url=jdbc:mysql://ip:3306/database-demo?useUnicode=true&characterEncoding=utf8&useSSL=false&&serverTimezone=UTC
cas.authn.jdbc.query[0].user=root
cas.authn.jdbc.query[0].password=******
cas.authn.jdbc.query[0].sql=select * from user where username = ?
cas.authn.jdbc.query[0].fieldPassword=password
# services
cas.tgc.secure=false
cas.serviceRegistry.initFromJson=true
server.max-http-header-size=2097152
server.use-forward-headers=true
server.connection-timeout=20000
server.error.include-stacktrace=ALWAYS
server.compression.enabled=true
server.compression.mime-types=application/javascript,application/json,application/xml,text/html,text/xml,text/plain
server.tomcat.max-http-post-size=2097152
server.tomcat.basedir=build/tomcat
server.tomcat.accesslog.enabled=true
server.tomcat.accesslog.pattern=%t %a "%r" %s (%D ms)
server.tomcat.accesslog.suffix=.log
server.tomcat.min-spare-threads=10
server.tomcat.max-threads=200
server.tomcat.port-header=X-Forwarded-Port
server.tomcat.protocol-header=X-Forwarded-Proto
server.tomcat.protocol-header-https-value=https
server.tomcat.remote-ip-header=X-FORWARDED-FOR
server.tomcat.uri-encoding=UTF-8
spring.http.encoding.charset=UTF-8
spring.http.encoding.enabled=true
spring.http.encoding.force=true
##
# CAS Cloud Bus Configuration
#
spring.cloud.bus.enabled=false
# Indicates that systemPropertiesOverride can be used.
# Set to false to prevent users from changing the default accidentally. Default true.
spring.cloud.config.allow-override=true
# External properties should override system properties.
spring.cloud.config.override-system-properties=false
# When allowOverride is true, external properties should take lowest priority, and not override any
# existing property sources (including local config files).
spring.cloud.config.override-none=false
# spring.cloud.bus.refresh.enabled=true
# spring.cloud.bus.env.enabled=true
# spring.cloud.bus.destination=CasCloudBus
# spring.cloud.bus.ack.enabled=true
endpoints.enabled=false
endpoints.sensitive=true
endpoints.restart.enabled=false
endpoints.shutdown.enabled=false
# Control the security of the management/actuator endpoints
# The 'enabled' flag below here controls the rendering of details for the health endpoint amongst other things.
management.security.enabled=true
management.security.roles=ACTUATOR,ADMIN
management.security.sessions=if_required
management.context-path=/status
management.add-application-context-header=false
# Define a CAS-specific "WARN" status code and its order
management.health.status.order=WARN, DOWN, OUT_OF_SERVICE, UNKNOWN, UP
# Control the security of the management/actuator endpoints
# With basic authentication, assuming Spring Security and/or relevant modules are on the classpath.
security.basic.authorize-mode=role
security.basic.path=/cas/status/**
# security.basic.enabled=true
# security.user.name=casuser
# security.user.password=
##
# CAS Web Application Session Configuration
#
server.session.timeout=300
server.session.cookie.http-only=true
server.session.tracking-modes=COOKIE
##
# CAS Thymeleaf View Configuration
#
spring.thymeleaf.encoding=UTF-8
spring.thymeleaf.cache=true
spring.thymeleaf.mode=HTML
spring.thymeleaf.template-resolver-order=100
##
# CAS Log4j Configuration
#
# logging.config=file:/etc/cas/log4j2.xml
server.context-parameters.isLog4jAutoInitializationDisabled=true
##
# CAS AspectJ Configuration
#
spring.aop.auto=true
spring.aop.proxy-target-class=true
##
# CAS Authentication Credentials
#
#cas.authn.accept.users=casuser::Mellon
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0modelVersion>
<groupId>org.xgllhzgroupId>
<artifactId>cas-sso-serverartifactId>
<packaging>warpackaging>
<version>1.0version>
<name>cas-sso-servername>
<properties>
<java.version>1.8java.version>
<project.build.sourceEncoding>UTF-8project.build.sourceEncoding>
<maven.compiler.source>1.8maven.compiler.source>
<maven.compiler.target>1.8maven.compiler.target>
<cas.version>5.3.16cas.version>
<springboot.version>2.7.0springboot.version>
<app.server>-tomcatapp.server>
<mainClassName>org.springframework.boot.loader.WarLaunchermainClassName>
<isExecutable>falseisExecutable>
<manifestFileToUse>${project.build.directory}/war/work/org.apereo.cas/cas-server-webapp${app.server}/META-INF/MANIFEST.MFmanifestFileToUse>
properties>
<dependencies>
<dependency>
<groupId>org.apereo.casgroupId>
<artifactId>cas-server-webapp${app.server}artifactId>
<version>${cas.version}version>
<type>wartype>
<scope>runtimescope>
dependency>
<dependency>
<groupId>org.apereo.casgroupId>
<artifactId>cas-server-support-jdbcartifactId>
<version>${cas.version}version>
dependency>
<dependency>
<groupId>org.apereo.casgroupId>
<artifactId>cas-server-support-jdbc-driversartifactId>
<version>${cas.version}version>
dependency>
<dependency>
<groupId>mysqlgroupId>
<artifactId>mysql-connector-javaartifactId>
<version>8.0.16version>
dependency>
dependencies>
<build>
<finalName>cas-sso-serverfinalName>
<plugins>
<plugin>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-maven-pluginartifactId>
<version>${springboot.version}version>
<configuration>
<mainClass>${mainClassName}mainClass>
<addResources>trueaddResources>
<executable>${isExecutable}executable>
<layout>WARlayout>
configuration>
<executions>
<execution>
<goals>
<goal>repackagegoal>
goals>
execution>
executions>
plugin>
<plugin>
<groupId>org.apache.maven.pluginsgroupId>
<artifactId>maven-war-pluginartifactId>
<version>2.6version>
<configuration>
<warName>cas-sso-serverwarName>
<failOnMissingWebXml>falsefailOnMissingWebXml>
<recompressZippedFiles>falserecompressZippedFiles>
<archive>
<compress>falsecompress>
<manifestFile>${manifestFileToUse}manifestFile>
archive>
<overlays>
<overlay>
<groupId>org.apereo.casgroupId>
<artifactId>cas-server-webapp${app.server}artifactId>
overlay>
overlays>
configuration>
plugin>
<plugin>
<groupId>org.apache.maven.pluginsgroupId>
<artifactId>maven-compiler-pluginartifactId>
<version>3.3version>
plugin>
plugins>
build>
project>
配置 tomcat 然后启动,就会出现登录页面:
cas-client 即用户访问的应用系统,即需要相互信任的系统,这个就比较简单了,加入 cas 配置即可。
pom 文件加入 cas-client 依赖:
<dependency>
<groupId>org.jasig.cas.clientgroupId>
<artifactId>cas-client-coreartifactId>
<version>3.6.4version>
dependency>
application.yml 文件加入 cas 配置:
################### spring 配置 ###################
spring:
application:
name: cas-sso-client
profiles:
active: dev
main:
allow-bean-definition-overriding: true
################### tomcat 配置 ###################
server:
port: 9626
servlet:
context-path: /cas-sso-client
tomcat:
uri-encoding: UTF-8
netty:
connection-timeout: 50000
ssl:
enabled: false
key-store: classpath:cas-jdk8
key-store-password: 962464
key-password: 962464
################### cas 配置 ###################
cas:
server:
base-url: http://localhost:9625/cas-sso-server
login-url: http://localhost:9625/cas-sso-server/login
client:
base-url: http://localhost:9626/
excluded-url: /static/*
模仿一个用户要访问的资源(如一个 hello world 接口?):
// ? ? ?
启动 cas-client,然后访问 hello world 接口,就会重定向到 cas-server 的登录页面,登录成功后就会跳转到 hello world 页面。
图片就不用贴了吧 O_O !
山茶花读不懂白玫瑰 人海遇见人海归