Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance. Project price only 1 $
You can buy this project and download/modify it how often you want.
/**
* This file is part of Graylog.
*
* Graylog is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Graylog is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Graylog. If not, see .
*/
package org.graylog2.shared.security;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.mgt.DefaultSecurityManager;
import org.apache.shiro.subject.Subject;
import org.apache.shiro.util.ThreadContext;
import org.glassfish.grizzly.http.server.Request;
import org.graylog2.rest.RestTools;
import org.jboss.netty.handler.ipfilter.IpSubnet;
import javax.annotation.Priority;
import javax.inject.Inject;
import javax.inject.Named;
import javax.inject.Provider;
import javax.ws.rs.BadRequestException;
import javax.ws.rs.Priorities;
import javax.ws.rs.container.ContainerRequestContext;
import javax.ws.rs.container.ContainerRequestFilter;
import javax.ws.rs.core.HttpHeaders;
import javax.ws.rs.core.MultivaluedMap;
import javax.ws.rs.core.SecurityContext;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.Base64;
import java.util.Set;
import static java.util.Objects.requireNonNull;
@Priority(Priorities.AUTHENTICATION)
public class ShiroSecurityContextFilter implements ContainerRequestFilter {
public static final String REQUEST_HEADERS = "REQUEST_HEADERS";
private final DefaultSecurityManager securityManager;
private Provider grizzlyRequestProvider;
private final Set trustedProxies;
@Inject
public ShiroSecurityContextFilter(DefaultSecurityManager securityManager,
Provider grizzlyRequestProvider,
@Named("trusted_proxies") Set trustedProxies) {
this.securityManager = requireNonNull(securityManager);
this.grizzlyRequestProvider = grizzlyRequestProvider;
this.trustedProxies = trustedProxies;
}
@Override
public void filter(ContainerRequestContext requestContext) throws IOException {
final boolean secure = requestContext.getSecurityContext().isSecure();
final MultivaluedMap headers = requestContext.getHeaders();
final Request grizzlyRequest = grizzlyRequestProvider.get();
final String host = RestTools.getRemoteAddrFromRequest(grizzlyRequest, trustedProxies);
final String authHeader = headers.getFirst(HttpHeaders.AUTHORIZATION);
// make headers available to authenticators, which otherwise have no access to them
ThreadContext.put(REQUEST_HEADERS, headers);
final SecurityContext securityContext;
if (authHeader != null && authHeader.startsWith("Basic")) {
final String base64UserPass = authHeader.substring(authHeader.indexOf(' ') + 1);
final String userPass = decodeBase64(base64UserPass);
final String[] split = userPass.split(":");
if (split.length != 2) {
throw new BadRequestException("Invalid credentials in Authorization header");
}
securityContext = createSecurityContext(split[0],
split[1],
secure,
SecurityContext.BASIC_AUTH,
host,
grizzlyRequest.getRemoteAddr(),
headers);
} else {
securityContext = createSecurityContext(null, null, secure, null, host,
grizzlyRequest.getRemoteAddr(),
headers);
}
requestContext.setSecurityContext(securityContext);
}
private String decodeBase64(String s) {
try {
return new String(Base64.getDecoder().decode(s), StandardCharsets.US_ASCII);
} catch (IllegalArgumentException e) {
return "";
}
}
private SecurityContext createSecurityContext(String userName,
String credential,
boolean isSecure,
String authcScheme,
String host,
String remoteAddr,
MultivaluedMap headers) {
final AuthenticationToken authToken;
if ("session".equalsIgnoreCase(credential)) {
// Basic auth: undefined:session is sent when the UI doesn't have a valid session id,
// we don't want to create a SessionIdToken in that case but fall back to looking at the headers instead
if ("undefined".equalsIgnoreCase(userName)) {
authToken = new HttpHeadersToken(headers, host, remoteAddr);
} else {
authToken = new SessionIdToken(userName, host);
}
} else if ("token".equalsIgnoreCase(credential)) {
authToken = new AccessTokenAuthToken(userName, host);
} else if (userName == null) { // without a username we default to using the header environment as potentially containing tokens used by plugins
authToken = new HttpHeadersToken(headers, host, remoteAddr);
} else { // otherwise we use the "standard" username/password combination
authToken = new UsernamePasswordToken(userName, credential, host);
}
final Subject subject = new Subject.Builder(securityManager)
.host(host)
.sessionCreationEnabled(true)
.buildSubject();
return new ShiroSecurityContext(subject, authToken, isSecure, authcScheme, headers);
}
}