javaweb项目接入CAS单点认证(含自身系统的三员过滤)
创始人
2024-05-02 14:49:01
0

一、搭建cas server
1.下载war包
在这里插入图片描述
2.打开cmd窗口执行以下命令,命令如下(指定ip):

keytool -genkey -v -alias casbm -keyalg RSA -keystore D:\cas\keystore\casbm.keystore -ext SAN=IP:192.168.2.166 

3.我们生成秘钥库后需要从秘钥库中导出证书,打开cmd窗口,命令如下:

keytool -export -trustcacerts -alias casbm -file D:/cas/keystore/casbm.cer -keystore D:/cas/keystore/casbm.keystore

4.我们从秘钥库导出证书后需要将证书导入到JDK证书库中,打开cmd窗口,命令如下,其中最后的路径为你本地jdk的路径,要确保该路径正确(此处密码不是自己设置的,是默认密码:changeit):
keytool -import -trustcacerts -alias casbm -file D:/cas/keystore/casbm.cer -keystore “D:/Configure/java/java8/jre/lib/security/cacerts”
5.由于cas需要https协议访问,所以我们要配置tomcat也支持https协议,我们找到我们的tomcat的server.xml文件,加入如下配置:


6.将之前下载的cas包放入tomcat中启动,首先将war包放入tomcat的webapps下,改名为cas,启动tomcat
7.启动完成后我们访问登录页面验证是否启动成功,访问地址如下,用户名为:casuser 密码为:Mellon:
https://localhost:8443/cas
8.用户名密码是在application.properties配置文件中指定的(需要删除原cas.war,避免覆盖)

##
# CAS Authentication Credentials
#
cas.authn.accept.users=dagly::most123456789
#cas.authn.jdbc.query[0].url=jdbc:kingbase8://192.168.2.166:54321/WANGLIAN#cas.authn.jdbc.query[0].user=WANGLIAN#cas.authn.jdbc.query[0].password=manager123#cas.authn.jdbc.query[0].sql=select * from hdrole where login_name = ?#cas.authn.jdbc.query[0].fieldPassword=password#cas.authn.jdbc.query[0].driverClass=com.kingbase8.Driver#cas.authn.jdbc.query[0].passwordEncoder.type=DEFAULT#cas.authn.jdbc.query[0].passwordEncoder.characterEncoding=GBK
#MD5加密策略#cas.authn.jdbc.query[0].passwordEncoder.encodingAlgorithm=MD5#是否开启json识别功能,默认为false
cas.serviceRegistry.initFromJson=true
#忽略https安全协议,使用 HTTP 协议
cas.tgc.secure=false
cas.logout.followServiceRedirects=true

9.使用数据库连接时加入jar:

cas-server-support-jdbc-5.3.1.jarcas-server-support-jdbc-drivers-5.3.1.jarcas-server-support-jdbc-authentication-5.3.1.jarconnector-java-5.1.34_1.jar

二、接入CAS 的client
1.修改tomcat的server.xml引入证书:,项目中引入cas-client-core-3.6.4.jar


2.在web.xml中加入配置(删掉注释,此处为了解释):

//单点登出的listener
org.jasig.cas.client.session.SingleSignOutHttpSessionListener//单点登出过滤器CAS Single Sign Out Filterorg.jasig.cas.client.session.SingleSignOutFilterCAS Single Sign Out Filter/*//自定义的顶层filer,用于处理请求FetchCasTicketFiltercom.hidy.auth.servlet.FetchCasTicketFilterFetchCasTicketFilter/*//认证过滤器,此处重写,用官方的无法配置不过滤的路径CASFiltercom.hidy.auth.servlet.AuthenticationFiltercasServerLoginUrlhttps://192.168.2.166:8443/cas/login//CAS server登录页serverNamehttp://192.168.2.166:8080///项目地址ignorePattern/defaultpsy.*|/theme/*|/LoginServlet|/images/*|/TransInterface//CASFilter/*CAS Validation Filter//认证拦截器org.jasig.cas.client.validation.Cas20ProxyReceivingTicketValidationFiltertargetBeanNameloginSinglePointScoreBpcasServerUrlPrefixhttps://192.168.2.166:8443/casserverNamehttp://192.168.2.166:8080/CAS Validation Filter/*//处理request,能够用request.getRemoteUser()获取当前登录人CAS HttpServletRequest Wrapper Filterorg.jasig.cas.client.util.HttpServletRequestWrapperFilterCAS HttpServletRequest Wrapper Filter/*//单点的登录servlet(即对原来的登录servlet复制,逻辑进行修改,原来的用于三员登录)LoginServletCascom.hidy.auth.servlet.LoginServletCasLoginServletCas/LoginServletCas

3.FetchCasTicketFilter代码,顶级过滤器

package com.hidy.auth.servlet;import java.io.IOException;import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;import org.jasig.cas.client.util.CommonUtils;import com.hidy.hdoa6.util.StaticData;import org.jasig.cas.client.util.CommonUtils;public class FetchCasTicketFilter implements Filter {@Overridepublic void destroy() {// TODO Auto-generated method stub}@Overridepublic void doFilter(ServletRequest req, ServletResponse res, FilterChain chain)throws IOException, ServletException {HttpServletRequest request = (HttpServletRequest) req;HttpServletResponse response=(HttpServletResponse) res;String path = request.getServletPath();Object id = request.getSession().getAttribute("UserID");String ticket = request.getParameter("ticket");String requestUri=request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+request.getContextPath()+"/";//对一些路径不拦截if(id == null && ticket==null && !(path.endsWith("defaultp.jsp") || path.endsWith(".js") || path.endsWith(".css") || path.endsWith("/LoginServlet")|| path.endsWith("/LoginServletCas")|| path.endsWith("/defaultpsy.jsp")|| path.endsWith(".png")||path.endsWith("/TransInterface"))) {String result = "";response.getWriter().print(result);response.getWriter().close();}else {//获取cas的ticket,看cas server配置的规则,如果是认证完即失效,则此处可以不写String queryString = request.getQueryString();if(queryString != null && queryString.contains("ticket")){Cookie cookie=new Cookie("ticket",queryString.substring(queryString.indexOf("=") + 1) );cookie.setMaxAge(Integer.MAX_VALUE);//将Cookie加到response中response.addCookie(cookie);}chain.doFilter(req, res);}}@Overridepublic void init(FilterConfig filterConfig) throws ServletException {}}

4.AuthenticationFilter代码(不一定一致,当前用的cas client core3.6.4,其他版本反编译后修改逻辑,主要是对不拦截路径的放行)

import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import org.jasig.cas.client.Protocol;
import org.jasig.cas.client.authentication.AuthenticationRedirectStrategy;
import org.jasig.cas.client.authentication.ContainsPatternUrlPatternMatcherStrategy;
import org.jasig.cas.client.authentication.DefaultAuthenticationRedirectStrategy;
import org.jasig.cas.client.authentication.DefaultGatewayResolverImpl;
import org.jasig.cas.client.authentication.EntireRegionRegexUrlPatternMatcherStrategy;
import org.jasig.cas.client.authentication.ExactUrlPatternMatcherStrategy;
import org.jasig.cas.client.authentication.GatewayResolver;
import org.jasig.cas.client.authentication.RegexUrlPatternMatcherStrategy;
import org.jasig.cas.client.authentication.UrlPatternMatcherStrategy;
import org.jasig.cas.client.configuration.ConfigurationKey;
import org.jasig.cas.client.configuration.ConfigurationKeys;
import org.jasig.cas.client.util.AbstractCasFilter;
import org.jasig.cas.client.util.CommonUtils;
import org.jasig.cas.client.util.ReflectUtils;
import org.jasig.cas.client.validation.Assertion;
public class AuthenticationFilter extends AbstractCasFilter {private String casServerLoginUrl;private boolean renew;private boolean gateway;private String method;private GatewayResolver gatewayStorage;private AuthenticationRedirectStrategy authenticationRedirectStrategy;private UrlPatternMatcherStrategy ignoreUrlPatternMatcherStrategyClass;private static final Map> PATTERN_MATCHER_TYPES = new HashMap();private String excludePaths;  public AuthenticationFilter() {this(Protocol.CAS2);}protected AuthenticationFilter(Protocol protocol) {super(protocol);this.renew = false;this.gateway = false;this.gatewayStorage = new DefaultGatewayResolverImpl();this.authenticationRedirectStrategy = new DefaultAuthenticationRedirectStrategy();this.ignoreUrlPatternMatcherStrategyClass = null;}protected void initInternal(FilterConfig filterConfig) throws ServletException {if (!this.isIgnoreInitConfiguration()) {super.initInternal(filterConfig);String loginUrl = this.getString(ConfigurationKeys.CAS_SERVER_LOGIN_URL);if (loginUrl != null) {this.setCasServerLoginUrl(loginUrl);} else {this.setCasServerUrlPrefix(this.getString(ConfigurationKeys.CAS_SERVER_URL_PREFIX));}this.setRenew(this.getBoolean(ConfigurationKeys.RENEW));this.setGateway(this.getBoolean(ConfigurationKeys.GATEWAY));this.setMethod(this.getString(ConfigurationKeys.METHOD));String ignorePattern = this.getString(ConfigurationKeys.IGNORE_PATTERN);String ignoreUrlPatternType = this.getString(ConfigurationKeys.IGNORE_URL_PATTERN_TYPE);Class gatewayStorageClass;if (ignorePattern != null) {gatewayStorageClass = (Class)PATTERN_MATCHER_TYPES.get(ignoreUrlPatternType);if (gatewayStorageClass != null) {this.ignoreUrlPatternMatcherStrategyClass = (UrlPatternMatcherStrategy)ReflectUtils.newInstance(gatewayStorageClass.getName(), new Object[0]);} else {try {this.logger.trace("Assuming {} is a qualified class name...", ignoreUrlPatternType);this.ignoreUrlPatternMatcherStrategyClass = (UrlPatternMatcherStrategy)ReflectUtils.newInstance(ignoreUrlPatternType, new Object[0]);} catch (IllegalArgumentException var7) {this.logger.error("Could not instantiate class [{}]", ignoreUrlPatternType, var7);}}if (this.ignoreUrlPatternMatcherStrategyClass != null) {this.ignoreUrlPatternMatcherStrategyClass.setPattern(ignorePattern);}}gatewayStorageClass = this.getClass(ConfigurationKeys.GATEWAY_STORAGE_CLASS);if (gatewayStorageClass != null) {this.setGatewayStorage((GatewayResolver)ReflectUtils.newInstance(gatewayStorageClass, new Object[0]));}Class authenticationRedirectStrategyClass = this.getClass(ConfigurationKeys.AUTHENTICATION_REDIRECT_STRATEGY_CLASS);if (authenticationRedirectStrategyClass != null) {this.authenticationRedirectStrategy = (AuthenticationRedirectStrategy)ReflectUtils.newInstance(authenticationRedirectStrategyClass, new Object[0]);}excludePaths = this.getString(new ConfigurationKey("ignorePattern", (Object)null));excludePaths = excludePaths.trim();}}public void init() {super.init();String message = String.format("one of %s and %s must not be null.", ConfigurationKeys.CAS_SERVER_LOGIN_URL.getName(), ConfigurationKeys.CAS_SERVER_URL_PREFIX.getName());CommonUtils.assertNotNull(this.casServerLoginUrl, message);}public final void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {HttpServletRequest request = (HttpServletRequest)servletRequest;HttpServletResponse response = (HttpServletResponse)servletResponse;
//三员用户直接放行        if(null!=request.getSession().getAttribute("isXtgly")||null!=request.getSession().getAttribute("isAqbmy")||null!=request.getSession().getAttribute("isAqsjy")) {filterChain.doFilter(request, response);return;}if (this.isRequestUrlExcluded(request)) {this.logger.debug("Request is ignored.");filterChain.doFilter(request, response);return;} else {HttpSession session = request.getSession(false);Assertion assertion = session != null ? (Assertion)session.getAttribute("_const_cas_assertion_") : null;if (assertion != null) {filterChain.doFilter(request, response);} else {String serviceUrl = this.constructServiceUrl(request, response);String ticket = this.retrieveTicketFromRequest(request);boolean wasGatewayed = this.gateway && this.gatewayStorage.hasGatewayedAlready(request, serviceUrl);if (!CommonUtils.isNotBlank(ticket) && !wasGatewayed) {this.logger.debug("no ticket and no assertion found");String modifiedServiceUrl;if (this.gateway) {this.logger.debug("setting gateway attribute in session");modifiedServiceUrl = this.gatewayStorage.storeGatewayInformation(request, serviceUrl);} else {modifiedServiceUrl = serviceUrl;}this.logger.debug("Constructed service url: {}", modifiedServiceUrl);String urlToRedirectTo = CommonUtils.constructRedirectUrl(this.casServerLoginUrl, this.getProtocol().getServiceParameterName(), modifiedServiceUrl, this.renew, this.gateway, this.method);this.logger.debug("redirecting to \"{}\"", urlToRedirectTo);this.authenticationRedirectStrategy.redirect(request, response, urlToRedirectTo);} else {filterChain.doFilter(request, response);}}}}public final void setRenew(boolean renew) {this.renew = renew;}public final void setGateway(boolean gateway) {this.gateway = gateway;}public void setMethod(String method) {this.method = method;}public final void setCasServerUrlPrefix(String casServerUrlPrefix) {this.setCasServerLoginUrl(CommonUtils.addTrailingSlash(casServerUrlPrefix) + "login");}public final void setCasServerLoginUrl(String casServerLoginUrl) {this.casServerLoginUrl = casServerLoginUrl;}public final void setGatewayStorage(GatewayResolver gatewayStorage) {this.gatewayStorage = gatewayStorage;}
//自行修改代码private boolean isRequestUrlExcluded(HttpServletRequest request) {if (this.ignoreUrlPatternMatcherStrategyClass == null) {return false;} else {StringBuffer urlBuffer = request.getRequestURL();if (request.getQueryString() != null) {urlBuffer.append("?").append(request.getQueryString());}String requestUri = urlBuffer.toString();return this.ignoreUrlPatternMatcherStrategyClass.matches(requestUri);}}public final void setIgnoreUrlPatternMatcherStrategyClass(UrlPatternMatcherStrategy ignoreUrlPatternMatcherStrategyClass) {this.ignoreUrlPatternMatcherStrategyClass = ignoreUrlPatternMatcherStrategyClass;}static {PATTERN_MATCHER_TYPES.put("CONTAINS", ContainsPatternUrlPatternMatcherStrategy.class);PATTERN_MATCHER_TYPES.put("REGEX", RegexUrlPatternMatcherStrategy.class);PATTERN_MATCHER_TYPES.put("FULL_REGEX", EntireRegionRegexUrlPatternMatcherStrategy.class);PATTERN_MATCHER_TYPES.put("EXACT", ExactUrlPatternMatcherStrategy.class);}
}

5.登录页验证是否已经cas登录

	String user=request.getRemoteUser();String casloginflag="false";if(!"".equals(user)&&null!=user){//已经在cas登录casloginflag="true";}为true是直接跳转到LoginServletCas

6.三员
复制一个登录页,登录servlet,不验证cas,只验证session中三员是否登录,此页面需要在web.xml中修改,放行此页面和相关servlet(包括上面AuthenticationFilter的逻辑处理)
参考资料:
CAS实现单点登录
自定义cas客户端核心过滤器AuthenticationFilter
其他

相关内容

热门资讯

安卓系统自带的网页,功能与特色... 你有没有发现,每次打开安卓手机,那熟悉的系统界面里总有一个默默无闻的小家伙——安卓系统自带的网页浏览...
美咖云系统安卓版,开启智能生活... 你有没有发现,最近手机上多了一个叫“美咖云系统安卓版”的小家伙?它就像一个魔法师,轻轻一点,就能让你...
安卓系统推荐最好的手机,盘点性... 你有没有想过,拥有一部性能卓越的手机,就像是拥有了移动的宝藏库?在这个信息爆炸的时代,一部好手机不仅...
安卓11系统能精简吗,释放潜能 你有没有发现,随着手机越来越智能,系统也越来越庞大?安卓11系统,这个最新的操作系统,是不是也让你觉...
安卓自动重启系统软件,揭秘原因... 手机突然自动重启,是不是感觉整个人都不好了?别急,今天就来和你聊聊这个让人头疼的安卓自动重启系统软件...
苹果手机x刷安卓系统,探索安卓... 你有没有想过,你的苹果手机X竟然也能刷上安卓系统?是的,你没听错,就是那个一直以来都和我们苹果手机X...
安卓系统智商低吗,智商低下的真... 你有没有想过,为什么安卓系统的智商总被调侃得好像有点低呢?是不是觉得它总是慢吞吞的,有时候还犯点小错...
安卓系统手机联系人,揭秘你的社... 你有没有发现,手机里的联系人列表就像是一个小小的社交圈呢?里面藏着我们的亲朋好友、工作伙伴,甚至还有...
安卓系统免费铃声下载,打造个性... 手机里那首老掉牙的铃声是不是让你觉得有点out了呢?别急,今天就来给你支个招,让你轻松给安卓手机换上...
安卓系统用哪个桌面好,打造个性... 你有没有发现,手机桌面可是我们每天都要面对的“脸面”呢?换一个好看的桌面,心情都能跟着好起来。那么,...
虚拟大师是安卓10系统,功能与... 你知道吗?最近在手机圈里,有个新玩意儿引起了不小的轰动,那就是虚拟大师!而且,更让人惊喜的是,这个虚...
安卓系统与苹果优缺点,系统优缺... 说到手机操作系统,安卓和苹果绝对是两大巨头,它们各有各的特色,就像两道不同的美味佳肴,让人难以抉择。...
安卓win双系统主板,融合与创... 你有没有想过,一台电脑如果既能流畅运行安卓系统,又能轻松驾驭Windows系统,那该有多爽啊?没错,...
安卓系统可精简软件,轻松提升手... 你有没有发现,手机里的安卓系统越来越庞大,软件也越装越多,有时候感觉手机就像个“大肚子”,不仅运行速...
安卓系统基于linux的代码,... 你有没有想过,那个陪伴你每天刷抖音、玩游戏、办公的安卓系统,其实背后有着一套复杂的基于Linux的代...
苹果和安卓的拍照系统,谁更胜一... 你有没有发现,现在手机拍照已经成为我们生活中不可或缺的一部分呢?无论是记录生活的点滴,还是捕捉美丽的...
苹果和安卓系统不同吗,系统差异... 你有没有想过,为什么你的手机里装的是苹果的iOS系统,而朋友的手机却是安卓系统呢?这两种系统,看似都...
安卓系统有多少级,揭秘其多级架... 你有没有想过,那个陪伴我们日常生活的安卓系统,它其实有着丰富的层级结构呢?没错,就是那个让我们的手机...
华为鸿蒙系统与安卓的,技术融合... 你知道吗?最近科技圈可是炸开了锅,华为鸿蒙系统与安卓的较量成为了大家热议的话题。这不,今天我就来给你...
什么安卓手机是苹果系统,搭载苹... 你有没有想过,为什么有些人宁愿花大价钱买苹果手机,而有些人却对安卓手机情有独钟呢?其实,这个问题背后...