📄 cryptedurlwebrequestcodingstrategy.java
字号:
/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */package org.apache.wicket.protocol.http.request;import java.io.UnsupportedEncodingException;import java.net.URLDecoder;import java.net.URLEncoder;import java.util.Locale;import java.util.Map;import java.util.regex.Matcher;import java.util.regex.Pattern;import org.apache.wicket.Application;import org.apache.wicket.IRequestTarget;import org.apache.wicket.Request;import org.apache.wicket.RequestCycle;import org.apache.wicket.WicketRuntimeException;import org.apache.wicket.protocol.http.RequestUtils;import org.apache.wicket.request.IRequestCodingStrategy;import org.apache.wicket.request.RequestParameters;import org.apache.wicket.request.target.coding.IRequestTargetUrlCodingStrategy;import org.apache.wicket.util.crypt.ICrypt;import org.apache.wicket.util.string.AppendingStringBuffer;import org.apache.wicket.util.string.Strings;import org.apache.wicket.util.value.ValueMap;import org.slf4j.Logger;import org.slf4j.LoggerFactory;/** * This is a request coding strategy which encrypts the URL and hence makes it impossible for users * to guess what is in the url and rebuild it manually. It uses the CryptFactory registered with the * application to encode and decode the URL. Hence, the coding algorithm must be a two-way one * (reversible). Because the algorithm is reversible, URLs which were bookmarkable before will * remain bookmarkable. * <p> * To register the request coding strategy to need to do the following: * * <pre> * protected IRequestCycleProcessor newRequestCycleProcessor() * { * return new WebRequestCycleProcessor() * { * protected IRequestCodingStrategy newRequestCodingStrategy() * { * return new CryptedUrlWebRequestCodingStrategy(new WebRequestCodingStrategy()); * } * }; * } * </pre> * * <b>Note:</b> When trying to hack urls in the browser an exception might be caught while decoding * the URL. By default, for safety reasons a very simple WicketRuntimeException is thrown. The * original stack trace is only logged. * * @author Juergen Donnerstag */public class CryptedUrlWebRequestCodingStrategy implements IRequestCodingStrategy{ /** log. */ private static final Logger log = LoggerFactory .getLogger(CryptedUrlWebRequestCodingStrategy.class); /** The default request coding strategy most of the methods are delegated to */ private final IRequestCodingStrategy defaultStrategy; /** * Construct. * * @param defaultStrategy * The default strategy most requests are forwarded to */ public CryptedUrlWebRequestCodingStrategy(final IRequestCodingStrategy defaultStrategy) { this.defaultStrategy = defaultStrategy; } /** * Decode the querystring of the URL * * @see org.apache.wicket.request.IRequestCodingStrategy#decode(org.apache.wicket.Request) */ public RequestParameters decode(final Request request) { String url = request.decodeURL(request.getURL()); String decodedQueryParams = decodeURL(url); if (decodedQueryParams != null) { // The difficulty now is that this.defaultStrategy.decode(request) // doesn't know the just decoded url which is why must create // a fake Request for. Request fakeRequest = new DecodedUrlRequest(request, url, decodedQueryParams); return defaultStrategy.decode(fakeRequest); } return defaultStrategy.decode(request); } /** * Encode the querystring of the URL * * @see org.apache.wicket.request.IRequestCodingStrategy#encode(org.apache.wicket.RequestCycle, * org.apache.wicket.IRequestTarget) */ public CharSequence encode(final RequestCycle requestCycle, final IRequestTarget requestTarget) { CharSequence url = defaultStrategy.encode(requestCycle, requestTarget); url = encodeURL(url); return url; } /** * @see org.apache.wicket.request.IRequestTargetMounter#mount( * org.apache.wicket.request.target.coding.IRequestTargetUrlCodingStrategy) */ public void mount(IRequestTargetUrlCodingStrategy urlCodingStrategy) { defaultStrategy.mount(urlCodingStrategy); } /** * @see org.apache.wicket.request.IRequestTargetMounter#unmount(java.lang.String) */ public void unmount(String path) { defaultStrategy.unmount(path); } /** * @see org.apache.wicket.request.IRequestTargetMounter#urlCodingStrategyForPath(java.lang.String) */ public IRequestTargetUrlCodingStrategy urlCodingStrategyForPath(String path) { return defaultStrategy.urlCodingStrategyForPath(path); } /** * @see org.apache.wicket.request.IRequestTargetMounter#pathForTarget(org.apache.wicket.IRequestTarget) */ public CharSequence pathForTarget(IRequestTarget requestTarget) { return defaultStrategy.pathForTarget(requestTarget); } /** * @see org.apache.wicket.request.IRequestTargetMounter#targetForRequest(org.apache.wicket.request.RequestParameters) */ public IRequestTarget targetForRequest(RequestParameters requestParameters) { return defaultStrategy.targetForRequest(requestParameters); } /** * Returns the given url encoded. * * @param url * The URL to encode * @return The encoded url */ protected CharSequence encodeURL(final CharSequence url) { // Get the crypt implementation from the application ICrypt urlCrypt = Application.get().getSecuritySettings().getCryptFactory().newCrypt(); if (urlCrypt != null) { // The url must have a query string, otherwise keep the url // unchanged final int pos = url.toString().indexOf('?'); if (pos > -1) { // The url's path CharSequence urlPrefix = url.subSequence(0, pos); // Extract the querystring String queryString = url.subSequence(pos + 1, url.length()).toString(); // if the querystring starts with a parameter like // "x=", than don't change the querystring as it // has been encoded already if (!queryString.startsWith("x=")) { // The length of the encrypted string depends on the // length of the original querystring. Let's try to // make the querystring shorter first without loosing // information. queryString = shortenUrl(queryString).toString(); // encrypt the query string String encryptedQueryString = urlCrypt.encryptUrlSafe(queryString); try { encryptedQueryString = URLEncoder.encode(encryptedQueryString, Application .get().getRequestCycleSettings().getResponseRequestEncoding()); } catch (UnsupportedEncodingException ex) { throw new WicketRuntimeException(ex); } // build the new complete url return new AppendingStringBuffer(urlPrefix).append("?x=").append( encryptedQueryString); } } } // we didn't change anything return url; } /** * Decode the "x" parameter of the querystring * * @param url * The encoded URL * @return The decoded 'x' parameter of the querystring */ protected String decodeURL(final String url) { int startIndex = url.indexOf("?x="); if (startIndex != -1) { try { startIndex = startIndex + 3; final int endIndex = url.indexOf("&", startIndex); String secureParam; if (endIndex == -1) { secureParam = url.substring(startIndex); } else { secureParam = url.substring(startIndex, endIndex); } secureParam = URLDecoder.decode(secureParam, Application.get() .getRequestCycleSettings().getResponseRequestEncoding()); // Get the crypt implementation from the application final ICrypt urlCrypt = Application.get().getSecuritySettings().getCryptFactory() .newCrypt(); // Decrypt the query string String queryString = urlCrypt.decryptUrlSafe(secureParam); // The querystring might have been shortened (length reduced). // In that case, lengthen the query string again. queryString = rebuildUrl(queryString); return queryString; } catch (Exception ex) { return onError(ex); } } return null; } /** * @param ex * * @return decoded URL */ protected String onError(final Exception ex) { log.error("Invalid URL", ex); throw new HackAttackException("Invalid URL"); } /**
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -