cas根据请求参数跳过验证

接上一篇 https://birdzhang.xyz/2018/05/15/Java%E6%94%B9%E5%86%99HttpServletRequest%E8%AF%B7%E6%B1%82%E5%8F%82%E6%95%B0/ ,这里说一下cas的坑(这里的cas是3.5版本)

虽然cas有CAS Authentication Filter,但是这个只是根据请求的uri过滤的,那么这里就出现了一个奇怪的bug

即使我在excludePaths里面添加了/test1/,但是当请求地址为/test1/123?ticket=123的时候,还是会去cas服务器验证!!!

我们来看代码:

CAS Authentication Filter 代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
package com.birdzhang.demo.check;

import java.io.IOException;

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.authentication.DefaultGatewayResolverImpl;
import org.jasig.cas.client.authentication.GatewayResolver;
import org.jasig.cas.client.util.AbstractCasFilter;
import org.jasig.cas.client.util.CommonUtils;
import org.jasig.cas.client.validation.Assertion;

public class AuthenticationFilter extends AbstractCasFilter{


/**
* 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;
}
}

可以看到在uri匹配到excludepath之后会走filterChain.doFilter(request, response);,由于我们并没有对filterChain做什么修改,所以最终还是跑到cas那里去了

修改后的代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
package com.birdzhang.plugin;

/**
* @author debo.zhang
*
*/
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.authentication.DefaultGatewayResolverImpl;
import org.jasig.cas.client.authentication.GatewayResolver;
import org.jasig.cas.client.util.AbstractCasFilter;
import org.jasig.cas.client.util.CommonUtils;
import org.jasig.cas.client.validation.Assertion;

public class AuthenticationFilter extends AbstractCasFilter{


/**
* 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 {
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;

//hack for 云桥
Map<String, String[]> paramsMap = request.getParameterMap();

if(null != paramsMap ) {
if(paramsMap.containsKey("ticket") && paramsMap.containsKey("operation")) {
/* String token = Arrays.toString(paramsMap.get("ticket"));
request.removeAttribute("ticket");
request.setAttribute("token", token.substring(1, token.length()-1));
filterChain.doFilter(request, response);
return;*/

/*StringBuffer paramsBuff = new StringBuffer();
for(String param: paramsMap.keySet()) {
String newString = Arrays.toString(paramsMap.get(param));
if(param.equals("ticket")) {
paramsBuff.append("&").append("eticket").append("=").append(newString.substring(1, newString.length()-1));
}else {
paramsBuff.append("&").append(param).append("=").append(newString.substring(1, newString.length()-1));
}
}
String port = request.getServerPort() == 80?"":":"+request.getServerPort();
String scheme = request.getScheme();
String host = request.getServerName();
String redirectUrl = String.format("%s://%s%s%s?%s",
scheme,
host,
port,
request.getRequestURI(),
paramsBuff.toString().substring(1)
);
System.out.println("request url:"+redirectUrl);
response.sendRedirect(redirectUrl);
return;*/

Map<String, String[]> extraParams = new HashMap<String, String[]>();
HttpServletRequest wrappedRequest = new PrettyFacesWrappedRequest(request, extraParams);
request.getRequestDispatcher(request.getRequestURI()).forward(wrappedRequest, response);
return;
}
}


// 该判断是自定义的对符合条件的url进行通过处理
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;
}
}