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

Java改写HttpServletRequest请求参数

为什么会有这个需求呢? 因为被 casAuthenticationFilter坑了

下一篇再说一下AuthenticationFilter的坑,这里主要说修改请求的参数

代码是从网上找的,找不到具体来源了,直接贴代码吧

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
package com.birdzhang.plugin;

import java.util.Collections;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;
import java.util.TreeMap;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;


/**
* @author birdzhang
*
*/
public class PrettyFacesWrappedRequest extends HttpServletRequestWrapper
{
private final Map<String, String[]> modifiableParameters;
private Map<String, String[]> allParameters = null;

/**
* Create a new request wrapper that will merge additional parameters into
* the request object without prematurely reading parameters from the
* original request.
*
* @param request
* @param additionalParams
*/
public PrettyFacesWrappedRequest(final HttpServletRequest request,
final Map<String, String[]> additionalParams)
{
super(request);
modifiableParameters = new HashMap<String, String[]>();
modifiableParameters.putAll(additionalParams);
}

@Override
public String getParameter(final String name)
{
String[] strings = getParameterMap().get(name);
if (strings != null)
{
return strings[0];
}
return super.getParameter(name);
}

@Override
public Map<String, String[]> getParameterMap()
{
if (allParameters == null)
{
allParameters = new TreeMap<String, String[]>();
Map<String, String[]> superMap = super.getParameterMap();
// 在这里根据你的需要修改
for (String key : superMap.keySet()) {
if(key.equals("ticket")) {
allParameters.put("token", superMap.get(key));
}else {
allParameters.put(key, superMap.get(key));
}
}
allParameters.putAll(modifiableParameters);
}
//Return an unmodifiable collection because we need to uphold the interface contract.
return Collections.unmodifiableMap(allParameters);
}

@Override
public Enumeration<String> getParameterNames()
{
return Collections.enumeration(getParameterMap().keySet());
}

@Override
public String[] getParameterValues(final String name)
{
return getParameterMap().get(name);
}
}

使用:

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

完美的将ticket参数替换为token参数