下面列出了javax.servlet.HttpMethodConstraintElement#io.undertow.UndertowMessages 实例代码,或者点击链接到github查看源代码,也可以在右侧发表评论。
public ServletPathMatch getServletHandlerByPath(final String path) {
ServletPathMatch exact = exactPathMatches.get(path);
if (exact != null) {
return exact;
}
SubstringMap.SubstringMatch<PathMatch> match = prefixMatches.get(path, path.length());
if (match != null) {
return handleMatch(path, match.getValue(), path.lastIndexOf('.'));
}
int extensionPos = -1;
for (int i = path.length() - 1; i >= 0; --i) {
final char c = path.charAt(i);
if (c == '/') {
match = prefixMatches.get(path, i);
if (match != null) {
return handleMatch(path, match.getValue(), extensionPos);
}
} else if (c == '.' && extensionPos == -1) {
extensionPos = i;
}
}
//this should never happen
//as the default servlet is aways registered under /*
throw UndertowMessages.MESSAGES.servletPathMatchFailed();
}
@Override
public AuthenticationMechanism create(String mechanismName, IdentityManager identityManager, FormParserFactory formParserFactory, Map<String, String> properties) {
String realm = properties.get(REALM);
String silent = properties.get(SILENT);
String charsetString = properties.get(CHARSET);
Charset charset = charsetString == null ? StandardCharsets.UTF_8 : Charset.forName(charsetString);
Map<Pattern, Charset> userAgentCharsets = new HashMap<>();
String userAgentString = properties.get(USER_AGENT_CHARSETS);
if(userAgentString != null) {
String[] parts = userAgentString.split(",");
if(parts.length % 2 != 0) {
throw UndertowMessages.MESSAGES.userAgentCharsetMustHaveEvenNumberOfItems(userAgentString);
}
for(int i = 0; i < parts.length; i += 2) {
Pattern pattern = Pattern.compile(parts[i]);
Charset c = Charset.forName(parts[i + 1]);
userAgentCharsets.put(pattern, c);
}
}
return new BasicAuthenticationMechanism(realm, mechanismName, silent != null && silent.equals("true"), identityManager, charset, userAgentCharsets);
}
@Override
public AuthenticationMechanismOutcome authenticate(HttpServerExchange exchange, SecurityContext securityContext) {
String principal = getPrincipal(exchange);
if (principal == null) {
return NOT_ATTEMPTED;
}
String session = getSession(exchange);
if (session == null) {
return NOT_ATTEMPTED;
}
Account account = identityManager.verify(principal, new PasswordCredential(session.toCharArray()));
if (account == null) {
securityContext.authenticationFailed(UndertowMessages.MESSAGES.authenticationFailed(principal), mechanismName);
return NOT_AUTHENTICATED;
}
securityContext.authenticationComplete(account, mechanismName, false);
return AUTHENTICATED;
}
@Override
public Object setAttribute(final String name, final Object value) {
if (value == null) {
return removeAttribute(name);
}
if (invalid) {
throw UndertowMessages.MESSAGES.sessionIsInvalid(sessionId);
}
final Object existing = attributes.put(name, value);
if (existing == null) {
sessionManager.sessionListeners.attributeAdded(this, name, value);
} else {
sessionManager.sessionListeners.attributeUpdated(this, name, value, existing);
}
bumpTimeout();
UndertowLogger.SESSION_LOGGER.tracef("Setting session attribute %s to %s for session %s", name, value, sessionId);
return existing;
}
private static int createCookie(final String name, final String value, int maxCookies, int cookieCount,
final Map<String, String> cookies, final Map<String, String> additional) {
if (!name.isEmpty() && name.charAt(0) == '$') {
if(additional.containsKey(name)) {
return cookieCount;
}
additional.put(name, value);
return cookieCount;
} else {
if (cookieCount == maxCookies) {
throw UndertowMessages.MESSAGES.tooManyCookies(maxCookies);
}
if(cookies.containsKey(name)) {
return cookieCount;
}
cookies.put(name, value);
return ++cookieCount;
}
}
@Override
public void run() {
while (exchange.isReadable()) {
try {
ByteBuf buffer = exchange.readAsync();
if (buffer == null) {
if (parser.isComplete()) {
exchange.putAttachment(FORM_DATA, data);
exchange.dispatch(SameThreadExecutor.INSTANCE, handler);
} else {
UndertowLogger.REQUEST_IO_LOGGER.ioException(UndertowMessages.MESSAGES.connectionTerminatedReadingMultiPartData());
exchange.setStatusCode(StatusCodes.INTERNAL_SERVER_ERROR);
exchange.endExchange();
}
return;
} else {
parser.parse(buffer);
}
} catch (IOException e) {
UndertowLogger.REQUEST_IO_LOGGER.ioException(e);
exchange.setStatusCode(StatusCodes.INTERNAL_SERVER_ERROR);
exchange.endExchange();
}
}
exchange.setReadHandler(this, exchange);
}
private IPAddressAccessControlHandler addRule(final String peer, final boolean deny) {
if (IP4_EXACT.matcher(peer).matches()) {
addIpV4ExactMatch(peer, deny);
} else if (IP4_WILDCARD.matcher(peer).matches()) {
addIpV4WildcardMatch(peer, deny);
} else if (IP4_SLASH.matcher(peer).matches()) {
addIpV4SlashPrefix(peer, deny);
} else if (IP6_EXACT.matcher(peer).matches()) {
addIpV6ExactMatch(peer, deny);
} else if (IP6_WILDCARD.matcher(peer).matches()) {
addIpV6WildcardMatch(peer, deny);
} else if (IP6_SLASH.matcher(peer).matches()) {
addIpV6SlashPrefix(peer, deny);
} else {
throw UndertowMessages.MESSAGES.notAValidIpPattern(peer);
}
return this;
}
@Override
public HandlerWrapper build(Map<String, Object> config) {
String[] acl = (String[]) config.get("acl");
Boolean defaultAllow = (Boolean) config.get("default-allow");
Integer failureStatus = (Integer) config.get("failure-status");
List<Holder> peerMatches = new ArrayList<>();
for(String rule :acl) {
String[] parts = rule.split(" ");
if(parts.length != 2) {
throw UndertowMessages.MESSAGES.invalidAclRule(rule);
}
if(parts[1].trim().equals("allow")) {
peerMatches.add(new Holder(parts[0].trim(), false));
} else if(parts[1].trim().equals("deny")) {
peerMatches.add(new Holder(parts[0].trim(), true));
} else {
throw UndertowMessages.MESSAGES.invalidAclRule(rule);
}
}
return new Wrapper(peerMatches, defaultAllow == null ? false : defaultAllow, failureStatus == null ? StatusCodes.FORBIDDEN : failureStatus);
}
/**
* Waits a set length of time for the handler to shut down
*
* @param millis The length of time
* @return <code>true</code> If the handler successfully shut down
*/
public boolean awaitShutdown(long millis) throws InterruptedException {
synchronized (lock) {
if (!shutdown) {
throw UndertowMessages.MESSAGES.handlerNotShutdown();
}
long end = System.currentTimeMillis() + millis;
int count = (int) activeRequestsUpdater.get(this);
while (count != 0) {
long left = end - System.currentTimeMillis();
if (left <= 0) {
return false;
}
lock.wait(left);
count = (int) activeRequestsUpdater.get(this);
}
return true;
}
}
protected PathResourceManager(long transferMinSize, boolean caseSensitive, boolean followLinks, boolean allowResourceChangeListeners, final String... safePaths) {
this.caseSensitive = caseSensitive;
this.followLinks = followLinks;
this.transferMinSize = transferMinSize;
this.allowResourceChangeListeners = allowResourceChangeListeners;
if (this.followLinks) {
if (safePaths == null) {
throw UndertowMessages.MESSAGES.argumentCannotBeNull("safePaths");
}
for (final String safePath : safePaths) {
if (safePath == null) {
throw UndertowMessages.MESSAGES.argumentCannotBeNull("safePaths");
}
}
this.safePaths.addAll(Arrays.asList(safePaths));
}
this.eTagFunction = NULL_ETAG_FUNCTION;
}
private PathResourceManager(Builder builder) {
this.allowResourceChangeListeners = builder.allowResourceChangeListeners;
if (builder.base == null) {
throw UndertowMessages.MESSAGES.argumentCannotBeNull("base");
}
String basePath = builder.base.normalize().toAbsolutePath().toString();
if (!basePath.endsWith(File.separator)) {
basePath = basePath + File.separatorChar;
}
this.base = basePath;
this.transferMinSize = builder.transferMinSize;
this.caseSensitive = builder.caseSensitive;
this.followLinks = builder.followLinks;
if (this.followLinks) {
if (builder.safePaths == null) {
throw UndertowMessages.MESSAGES.argumentCannotBeNull("safePaths");
}
for (final String safePath : builder.safePaths) {
if (safePath == null) {
throw UndertowMessages.MESSAGES.argumentCannotBeNull("safePaths");
}
}
this.safePaths.addAll(Arrays.asList(builder.safePaths));
}
this.eTagFunction = builder.eTagFunction;
}
@Override
public HandlerWrapper build(Map<String, Object> config) {
String[] acl = (String[]) config.get("acl");
Boolean defaultAllow = (Boolean) config.get("default-allow");
ExchangeAttribute attribute = (ExchangeAttribute) config.get("attribute");
List<AclMatch> peerMatches = new ArrayList<>();
for(String rule :acl) {
String[] parts = rule.split(" ");
if(parts.length != 2) {
throw UndertowMessages.MESSAGES.invalidAclRule(rule);
}
if(parts[1].trim().equals("allow")) {
peerMatches.add(new AclMatch(false, parts[0].trim()));
} else if(parts[1].trim().equals("deny")) {
peerMatches.add(new AclMatch(true, parts[0].trim()));
} else {
throw UndertowMessages.MESSAGES.invalidAclRule(rule);
}
}
return new Wrapper(peerMatches, defaultAllow == null ? false : defaultAllow, attribute);
}
@Override
public Cookie setSameSiteMode(final String sameSiteMode) {
if (sameSiteMode != null) {
switch (sameSiteMode.toLowerCase(Locale.ENGLISH)) {
case "strict":
this.setSameSite(true);
this.sameSiteMode = "Strict";
break;
case "lax":
this.setSameSite(true);
this.sameSiteMode = "Lax";
break;
default:
throw UndertowMessages.MESSAGES.invalidSameSiteMode(sameSiteMode);
}
}
return this;
}
private static IllegalStateException error(final String string, int pos, String reason) {
StringBuilder b = new StringBuilder();
int linePos = 0;
for (int i = 0; i < string.length(); ++i) {
if (string.charAt(i) == '\n') {
if (i >= pos) {
//truncate the string at the error line
break;
} else {
linePos = 0;
}
} else if (i < pos) {
linePos++;
}
b.append(string.charAt(i));
}
b.append('\n');
for (int i = 0; i < linePos; ++i) {
b.append(' ');
}
b.append('^');
throw UndertowMessages.MESSAGES.errorParsingPredicateString(reason, b.toString());
}
/**
* Dispatches this request to the given executor. Once the call stack returns
* the given runnable will be submitted to the executor.
* <p>
* In general handlers should first check the value of {@link #isInIoThread()} before
* calling this method, and only dispatch if the request is actually running in the IO
* thread.
*
* @param runnable The task to run
* @throws IllegalStateException If this exchange has already been dispatched
*/
public HttpServerExchange dispatch(final Executor executor, final Runnable runnable) {
if (isExecutingHandlerChain()) {
if (executor != null) {
this.dispatchExecutor = executor;
}
state |= FLAG_DISPATCHED;
if (delegate.isIoOperationQueued()) {
throw UndertowMessages.MESSAGES.resumedAndDispatched();
}
this.dispatchTask = runnable;
} else {
if (executor == null) {
delegate.getWorker().execute(runnable);
} else {
executor.execute(runnable);
}
}
return this;
}
public <T> void writeAsync(ByteBuf data, boolean last, IoCallback<T> callback, T context) {
if (data == null && !last) {
throw new IllegalArgumentException("cannot call write with a null buffer and last being false");
}
if (isResponseComplete() || anyAreSet(state, FLAG_LAST_DATA_QUEUED)) {
if (last && data == null) {
callback.onComplete(delegate, context);
return;
}
callback.onException(delegate, context, new IOException(UndertowMessages.MESSAGES.responseComplete()));
return;
}
if (last) {
state |= FLAG_LAST_DATA_QUEUED;
}
delegate.getOutputChannel().writeAsync(data, last, callback, context);
}
/**
* Change the status code for this response. If not specified, the code will be a {@code 200}. Setting
* the status code after the response headers have been transmitted has no effect.
*
* @param statusCode the new code
* @throws IllegalStateException if a response or upgrade was already sent
*/
public HttpServerExchange setStatusCode(final int statusCode) {
if (statusCode < 0 || statusCode > 999) {
throw new IllegalArgumentException("Invalid response code");
}
int oldVal = state;
if (allAreSet(oldVal, FLAG_RESPONSE_SENT)) {
throw UndertowMessages.MESSAGES.responseAlreadyStarted();
}
if (statusCode >= 500) {
if (UndertowLogger.ERROR_RESPONSE.isDebugEnabled()) {
UndertowLogger.ERROR_RESPONSE.debugf(new RuntimeException(), "Setting error code %s for exchange %s", statusCode, this);
}
}
delegate.setStatusCode(statusCode);
return this;
}
@Override
public PooledObject allocate() {
final T obj = supplier.get();
return new PooledObject() {
private volatile boolean closed = false;
@Override
public T getObject() {
if(closed) {
throw UndertowMessages.MESSAGES.objectIsClosed();
}
return obj;
}
@Override
public void close() {
closed = true;
consumer.accept(obj);
}
};
}
/**
* Adds a path prefix and a handler for that path. If the path does not start
* with a / then one will be prepended.
* <p>
* The match is done on a prefix bases, so registering /foo will also match /bar. Exact
* path matches are taken into account first.
* <p>
* If / is specified as the path then it will replace the default handler.
*
* @param path The path
* @param handler The handler
*/
public synchronized PathMatcher addPrefixPath(final String path, final T handler) {
if (path.isEmpty()) {
throw UndertowMessages.MESSAGES.pathMustBeSpecified();
}
final String normalizedPath = URLUtils.normalizeSlashes(path);
if (PathMatcher.STRING_PATH_SEPARATOR.equals(normalizedPath)) {
this.defaultHandler = handler;
return this;
}
paths.put(normalizedPath, handler);
buildLengths();
return this;
}
public synchronized PathMatcher removePrefixPath(final String path) {
if (path == null || path.isEmpty()) {
throw UndertowMessages.MESSAGES.pathMustBeSpecified();
}
final String normalizedPath = URLUtils.normalizeSlashes(path);
if (PathMatcher.STRING_PATH_SEPARATOR.equals(normalizedPath)) {
defaultHandler = null;
return this;
}
paths.remove(normalizedPath);
buildLengths();
return this;
}
/**
* Escapes any double quotes in the given string.
*
* @param s the input string
* @param beginIndex start index inclusive
* @param endIndex exclusive
* @return The (possibly) escaped string
*/
private static String escapeDoubleQuotes(String s, int beginIndex, int endIndex) {
if (s == null || s.length() == 0 || s.indexOf('"') == -1) {
return s;
}
StringBuilder b = new StringBuilder();
for (int i = beginIndex; i < endIndex; i++) {
char c = s.charAt(i);
if (c == '\\' ) {
b.append(c);
//ignore the character after an escape, just append it
if (++i>=endIndex) throw UndertowMessages.MESSAGES.invalidEscapeCharacter();
b.append(s.charAt(i));
} else if (c == '"')
b.append('\\').append('"');
else
b.append(c);
}
return b.toString();
}
public static void validateCookieValue(String value) {
int start = 0;
int end = value.length();
if (end > 1 && value.charAt(0) == '"' && value.charAt(end - 1) == '"') {
start = 1;
end--;
}
char[] chars = value.toCharArray();
for (int i = start; i < end; i++) {
char c = chars[i];
if (c < 0x21 || c == 0x22 || c == 0x2c || c == 0x3b || c == 0x5c || c == 0x7f) {
throw UndertowMessages.MESSAGES.invalidCookieValue(Integer.toString(c));
}
}
}
public static void validateDomain(String domain) {
int i = 0;
int prev = -1;
int cur = -1;
char[] chars = domain.toCharArray();
while (i < chars.length) {
prev = cur;
cur = chars[i];
if (!domainValid.get(cur)) {
throw UndertowMessages.MESSAGES.invalidCookieDomain(domain);
}
// labels must start with a letter or number
if ((prev == '.' || prev == -1) && (cur == '.' || cur == '-')) {
throw UndertowMessages.MESSAGES.invalidCookieDomain(domain);
}
// labels must end with a letter or number
if (prev == '-' && cur == '.') {
throw UndertowMessages.MESSAGES.invalidCookieDomain(domain);
}
i++;
}
// domain must end with a label
if (cur == '.' || cur == '-') {
throw UndertowMessages.MESSAGES.invalidCookieDomain(domain);
}
}
public static InetAddress parseIpv4Address(String addressString) throws IOException {
String[] parts = addressString.split("\\.");
if (parts.length != 4) {
throw UndertowMessages.MESSAGES.invalidIpAddress(addressString);
}
byte[] data = new byte[4];
for (int i = 0; i < 4; ++i) {
String part = parts[i];
if (part.length() == 0 || (part.charAt(0) == '0' && part.length() > 1)) {
//leading zeros are not allowed
throw UndertowMessages.MESSAGES.invalidIpAddress(addressString);
}
data[i] = (byte) Integer.parseInt(part);
}
return InetAddress.getByAddress(data);
}
public synchronized PathTemplateMatcher<T> add(final PathTemplate template, final T value) {
Set<PathTemplateHolder> values = pathTemplateMap.get(trimBase(template));
Set<PathTemplateHolder> newValues;
if (values == null) {
newValues = new TreeSet<>();
} else {
newValues = new TreeSet<>(values);
}
PathTemplateHolder holder = new PathTemplateHolder(value, template);
if (newValues.contains(holder)) {
PathTemplate equivalent = null;
for (PathTemplateHolder item : newValues) {
if (item.compareTo(holder) == 0) {
equivalent = item.template;
break;
}
}
throw UndertowMessages.MESSAGES.matcherAlreadyContainsTemplate(template.getTemplateString(), equivalent.getTemplateString());
}
newValues.add(holder);
pathTemplateMap.put(trimBase(template), newValues);
buildLengths();
return this;
}
@Override
public Set<String> setServletSecurity(final ServletSecurityElement constraint) {
if (constraint == null) {
throw UndertowMessages.MESSAGES.argumentCannotBeNull("constraint");
}
DeploymentInfo deploymentInfo = deployment.getDeploymentInfo();
//this is not super efficient, but it does not really matter
final Set<String> urlPatterns = new HashSet<>();
for (SecurityConstraint sc : deploymentInfo.getSecurityConstraints()) {
for (WebResourceCollection webResources : sc.getWebResourceCollections()) {
urlPatterns.addAll(webResources.getUrlPatterns());
}
}
final Set<String> ret = new HashSet<>();
for (String url : servletInfo.getMappings()) {
if (urlPatterns.contains(url)) {
ret.add(url);
}
}
ServletSecurityInfo info = new ServletSecurityInfo();
servletInfo.setServletSecurityInfo(info);
info.setTransportGuaranteeType(constraint.getTransportGuarantee() == CONFIDENTIAL ? TransportGuaranteeType.CONFIDENTIAL : TransportGuaranteeType.NONE)
.setEmptyRoleSemantic(emptyRoleSemantic(constraint.getEmptyRoleSemantic()))
.addRolesAllowed(constraint.getRolesAllowed());
for (final HttpMethodConstraintElement methodConstraint : constraint.getHttpMethodConstraints()) {
info.addHttpMethodSecurityInfo(new HttpMethodSecurityInfo()
.setTransportGuaranteeType(methodConstraint.getTransportGuarantee() == CONFIDENTIAL ? TransportGuaranteeType.CONFIDENTIAL : TransportGuaranteeType.NONE)
.setMethod(methodConstraint.getMethodName())
.setEmptyRoleSemantic(emptyRoleSemantic(methodConstraint.getEmptyRoleSemantic()))
.addRolesAllowed(methodConstraint.getRolesAllowed()));
}
return ret;
}
public static ServletRequestContext requireCurrent() {
SecurityManager sm = System.getSecurityManager();
if(sm != null) {
sm.checkPermission(GET_CURRENT_REQUEST);
}
ServletRequestContext attachments = CURRENT.get();
if (attachments == null) {
throw UndertowMessages.MESSAGES.noRequestActive();
}
return attachments;
}
private AuthenticationState transition() {
if (currentMethod != null) {
final AuthenticationMechanism mechanism = currentMethod.item;
currentMethod = currentMethod.next;
AuthenticationMechanismOutcome outcome = mechanism.authenticate(exchange, SecurityContextImpl.this);
if(UndertowLogger.SECURITY_LOGGER.isDebugEnabled()) {
UndertowLogger.SECURITY_LOGGER.tracef("Authentication outcome was %s with method %s for %s", outcome, mechanism, exchange.getRequestURI());
if(UndertowLogger.SECURITY_LOGGER.isTraceEnabled()) {
UndertowLogger.SECURITY_LOGGER.tracef("Contents of exchange after authentication attempt is %s", exchange);
}
}
if (outcome == null) {
throw UndertowMessages.MESSAGES.authMechanismOutcomeNull();
}
switch (outcome) {
case AUTHENTICATED:
// TODO - Should verify that the mechanism did register an authenticated Account.
return AuthenticationState.AUTHENTICATED;
case NOT_AUTHENTICATED:
// A mechanism attempted to authenticate but could not complete, this now means that
// authentication is required and challenges need to be sent.
setAuthenticationRequired();
return AuthenticationState.ATTEMPTED;
case NOT_ATTEMPTED:
// Time to try the next mechanism.
return transition();
default:
throw new IllegalStateException();
}
} else {
// Reached the end of the mechanisms and no mechanism authenticated for us to reach this point.
return AuthenticationState.ATTEMPTED;
}
}
@Override
public long getCreationTime() {
if (invalid) {
throw UndertowMessages.MESSAGES.sessionIsInvalid(sessionId);
}
return creationTime;
}
@Override
public long getLastAccessedTime() {
if (invalid) {
throw UndertowMessages.MESSAGES.sessionIsInvalid(sessionId);
}
return lastAccessed;
}