CAS单点登录方案配置
来源:互联网 发布:小学英语听力软件 编辑:程序博客网 时间:2024/06/07 03:26
CAS单点登录方案
本文将简介cas单点登录方案,如有不对,欢迎指正
web.xml配置
cas在网站中是以多个过滤器的方式去执行,如下配置:1.身份认证过滤器,2.ticket校验拦截器,3实现HttpServletRequest请求,可以通过HttpServletRequest的getRemoteUser()方法获得SSO登录用户名,4.获取登录用户名,如AssertionHolder.getAssertion().getPrincipal().getName():
<listener> <listener-class>org.jasig.cas.client.session.SingleSignOutHttpSessionListener</listener-class> </listener> <!-- 该过滤器用于实现单点登出功能,可选配置。 --> <filter> <filter-name>CAS Single Sign Out Filter</filter-name> <filter-class>org.jasig.cas.client.session.SingleSignOutFilter</filter-class> </filter> <filter-mapping> <filter-name>CAS Single Sign Out Filter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> <!-- 该过滤器负责用户的认证工作,必须启用它 --> <filter> <filter-name>CASFilter</filter-name> <filter-class>com.youyuan.chat.filter.AuthenticationFilter</filter-class> <init-param> <param-name>casServerLoginUrl</param-name> <!-- 配置服务端登录地址 --> <param-value>配置服务端登陆地址</param-value> </init-param> <init-param> <!--配置,在session 中放入username的地址(后台工程项目地址)。 --> <param-name>serverName</param-name> <param-value>需要访问的项目的地址</param-value> </init-param> <!-- 配置白名单的url --> <init-param> <param-name>excludePaths</param-name> <!-- 匹配/api/或者/resources/或者.txt结尾--> <param-value>.*/(api/|resources/|.*\\.txt$).*</param-value> </init-param> </filter> <filter-mapping> <filter-name>CASFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> <!-- 该过滤器负责对Ticket的校验工作,必须启用它 --> <filter> <filter-name>CAS Validation Filter</filter-name> <filter-class>org.jasig.cas.client.validation.Cas20ProxyReceivingTicketValidationFilter</filter-class> <!--配置服务端校验地址--> <init-param> <param-name>casServerUrlPrefix</param-name> <param-value> 配置服务端校验地址</param-value> </init-param> <!--配置后台项目地址地址--> <init-param> <param-name>serverName</param-name> <param-value>配置访问项目地址</param-value> </init-param> </filter> <filter-mapping> <filter-name>CAS Validation Filter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> <!-- 该过滤器负责实现HttpServletRequest请求,可以通过HttpServletRequest的getRemoteUser()方法获得SSO登录用户名,可选配置 --> <filter> <filter-name>CAS HttpServletRequest Wrapper Filter</filter-name> <filter-class>org.jasig.cas.client.util.HttpServletRequestWrapperFilter</filter-class> </filter> <filter-mapping> <filter-name>CAS HttpServletRequest Wrapper Filter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> <!-- 该过滤器org.jasig.cas.client.util.AssertioHolder用来获取登录用户名,如AssertionHolder.getAssertion().getPrincipal().getName() --> <filter> <filter-name>CAS Assertion Thread Local Filter</filter-name> <filter-class>org.jasig.cas.client.util.AssertionThreadLocalFilter</filter-class> </filter> <filter-mapping> <filter-name>CAS Assertion Thread Local Filter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> <!-- 以上是单点登录 -->
其中第一个身份认证拦截器可自定义实现,如下:
public class AuthenticationFilter extends AbstractCasFilter{ private static final Logger log = Logger.getLogger(AuthenticationFilter.class); /** * The URL to the CAS Server login. */ private String casServerLoginUrl; /** * Whether to send the renew request or not. */ private boolean renew = false; /** * Whether to send the gateway request or not. */ private boolean gateway = false; //添加属性,这里用来存放不过滤地址正则表达式,可以根据自己需求定制---1 private String excludePaths; private GatewayResolver gatewayStorage = new DefaultGatewayResolverImpl(); protected void initInternal(final FilterConfig filterConfig) throws ServletException { if (!isIgnoreInitConfiguration()) { super.initInternal(filterConfig); setCasServerLoginUrl(getPropertyFromInitParams(filterConfig, "casServerLoginUrl", null)); log.trace("Loaded CasServerLoginUrl parameter: " + this.casServerLoginUrl); setRenew(parseBoolean(getPropertyFromInitParams(filterConfig, "renew", "false"))); log.trace("Loaded renew parameter: " + this.renew); setGateway(parseBoolean(getPropertyFromInitParams(filterConfig, "gateway", "false"))); log.trace("Loaded gateway parameter: " + this.gateway); final String gatewayStorageClass = getPropertyFromInitParams(filterConfig, "gatewayStorageClass", null); if (gatewayStorageClass != null) { try { this.gatewayStorage = (GatewayResolver) Class.forName(gatewayStorageClass).newInstance(); } catch (final Exception e) { log.error(e,e); throw new ServletException(e); } } //自定义添加代码,用来读取web配置文件中excludes属性值 ---2 excludePaths = getPropertyFromInitParams(filterConfig, "excludePaths", null);//filterConfig.getInitParameter("excludePaths"); excludePaths = excludePaths.trim(); } } public void init() { super.init(); CommonUtils.assertNotNull(this.casServerLoginUrl, "casServerLoginUrl cannot be null."); } // url判断逻辑,这里大家可以根据自己需要来制订规则 private boolean isExclude(String uri){ boolean isInWhiteList = false; if(excludePaths!=null&& uri!=null){ isInWhiteList = uri.matches(excludePaths); } return isInWhiteList; } public final void doFilter(final ServletRequest servletRequest, final ServletResponse servletResponse, final FilterChain filterChain) throws IOException, ServletException { final HttpServletRequest request = (HttpServletRequest) servletRequest; final HttpServletResponse response = (HttpServletResponse) servletResponse; final HttpSession session = request.getSession(false); final Assertion assertion = session != null ? (Assertion) session.getAttribute(CONST_CAS_ASSERTION) : null; // 该判断是自定义的对符合条件的url进行通过处理 ---3 if(isExclude(request.getRequestURI())){ filterChain.doFilter(request, response); return; } if (assertion != null) { filterChain.doFilter(request, response); return; } final String serviceUrl = constructServiceUrl(request, response); final String ticket = CommonUtils.safeGetParameter(request,getArtifactParameterName()); final boolean wasGatewayed = this.gatewayStorage.hasGatewayedAlready(request, serviceUrl); if (CommonUtils.isNotBlank(ticket) || wasGatewayed) { filterChain.doFilter(request, response); return; } final String modifiedServiceUrl; log.debug("no ticket and no assertion found"); if (this.gateway) { log.debug("setting gateway attribute in session"); modifiedServiceUrl = this.gatewayStorage.storeGatewayInformation(request, serviceUrl); } else { modifiedServiceUrl = serviceUrl; } if (log.isDebugEnabled()) { log.debug("Constructed service url: " + modifiedServiceUrl); } final String urlToRedirectTo = CommonUtils.constructRedirectUrl(this.casServerLoginUrl, getServiceParameterName(), modifiedServiceUrl, this.renew, this.gateway); if (log.isDebugEnabled()) { log.debug("redirecting to \"" + urlToRedirectTo + "\""); } response.sendRedirect(urlToRedirectTo); } public final void setRenew(final boolean renew) { this.renew = renew; } public final void setGateway(final boolean gateway) { this.gateway = gateway; } public final void setCasServerLoginUrl(final String casServerLoginUrl) { this.casServerLoginUrl = casServerLoginUrl; } public final void setGatewayStorage(final GatewayResolver gatewayStorage) { this.gatewayStorage = gatewayStorage; } }
此自定义代码新增了对于部分不需要受限资源的判断。
cas认证流程:
用户首次登录时流程如下:
1)、用户浏览器访问系统A需登录受限资源,此时进行登录检查,发现未登录,然后进行获取票据操作,发现没有票据。
2)、系统A发现该请求需要登录,将请求重定向到认证中心,获取全局票据操作,没有,进行登录。
3)、认证中心呈现登录页面,用户登录,登录成功后,认证中心重定向请求到系统A,并附上认证通过令牌,此时认证中心同时生成了全局票据。
4)、此时再次进行登录检查,发现未登录,然后再次获取票据操作,此时可以获得票据(令牌),系统A与认证中心通信,验证令牌有效,证明用户已登录。
5)、系统A将受限资源返给用户。
其中需要注意的是:
- 浏览器与认证中心维持一个全局会话,浏览器与访问资源维护一个局部会话,当登出的时候,全局会话与局部会话一起被中断。
- ticket的认证,在cas服务端维使用map维护了用户登录票据CASTGC与ticket之间的关系,所以当cas客户端发起ticket真实性验证的时候,可以根据CASTGC获取真实ticket与需要比对的ticket对比,若一致,对比通过。
另外,推荐http://www.imooc.com/article/3720 cas系列文章,写的很棒,受益匪浅。
阅读全文
1 0
- CAS单点登录方案配置
- CAS单点登录配置
- CAS单点登录配置
- CAS单点登录配置
- cas 单点登录配置速成
- CAS单点登录配置笔记
- cas单点登录配置速成
- CAS单点登录详细配置
- cas单点登录服务配置
- cas 单点登录,退出配置
- Cas单点登录客户端配置
- 单点登录--CAS服务器配置
- cas单点登录服务器配置
- cas系列(二)--cas单点登录配置
- Cas单点登录(6)Cas Client配置
- CAS单点登录服务器的配置
- openjweb平台配置cas server单点登录
- liferay+cas sso单点登录 配置
- 水晶头接法
- iOS Quartz绘图
- Qt在Windows下的三种编程环境搭建
- 【javascript知识进阶】this和闭包
- HDU 1238 Substrings(KMP+暴力枚举)
- CAS单点登录方案配置
- Exception in thread "AWT-Shutdown" java.lang.OutOfMemoryError: PermGen space
- [good]Selenium入门教程
- Spring Boot Actuator 401无权限访问
- 微信第三方平台开发经验总结(五):接收授权方授权请求并保存授权方信息
- Integer的==判断问题
- 什么是区块链
- php中的$_REQUEST是什么意思
- strncpy与snprintf 的用法比较