All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.apache.pulsar.broker.authentication.SaslRoleToken Maven / Gradle / Ivy

/*
 * 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.pulsar.broker.authentication;

import java.security.Principal;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.StringTokenizer;
import javax.naming.AuthenticationException;
import lombok.extern.slf4j.Slf4j;

@Slf4j
public class SaslRoleToken implements Principal {

    /**
     * Constant that identifies an anonymous request.
     */
    public static final SaslRoleToken ANONYMOUS = new SaslRoleToken();

    private static final String ATTR_SEPARATOR = "&";
    private static final String USER_ROLE = "u";
    private static final String EXPIRES = "e";
    private static final String SESSION = "i";

    private static final Set ATTRIBUTES =
        new HashSet(Arrays.asList(USER_ROLE,  EXPIRES,  SESSION));

    private String userRole;
    private String session;
    private long expires;
    private String token;

    private SaslRoleToken() {
        userRole = null;
        session = null;
        expires = -1;
        token = "ANONYMOUS";
        generateToken();
    }

    private static final String ILLEGAL_ARG_MSG = " is NULL, empty or contains a '" + ATTR_SEPARATOR + "'";

    /**
     * Creates an authentication token.
     *
     * @param userRole user name.
     * @param session the sessionId.
     * (System.currentTimeMillis() + validityPeriod).
     */
    public SaslRoleToken(String userRole, String session) {
        checkForIllegalArgument(session, "session");
        this.userRole = userRole;
        this.session = session;
        this.expires = -1;
        generateToken();
    }

    public SaslRoleToken(String userRole, String session, long expires) {
        checkForIllegalArgument(userRole, "userRole");
        checkForIllegalArgument(session, "session");
        this.userRole = userRole;
        this.session = session;
        this.expires = expires;
        generateToken();
    }

    /**
     * Check if the provided value is invalid. Throw an error if it is invalid, NOP otherwise.
     *
     * @param value the value to check.
     * @param name the parameter name to use in an error message if the value is invalid.
     */
    private static void checkForIllegalArgument(String value, String name) {
        if (value == null || value.length() == 0 || value.contains(ATTR_SEPARATOR)) {
            throw new IllegalArgumentException(name + ILLEGAL_ARG_MSG);
        }
    }

    /**
     * Sets the expiration of the token.
     *
     * @param expires expiration time of the token in milliseconds since the epoch.
     */
    public void setExpires(long expires) {
        if (this != SaslRoleToken.ANONYMOUS) {
            this.expires = expires;
            generateToken();
        }
    }

    /**
     * Generates the token.
     */
    private void generateToken() {
        StringBuilder sb = new StringBuilder();
        sb.append(USER_ROLE).append("=").append(getUserRole()).append(ATTR_SEPARATOR);
        sb.append(SESSION).append("=").append(getSession()).append(ATTR_SEPARATOR);
        sb.append(EXPIRES).append("=").append(getExpires());
        token = sb.toString();
    }

    /**
     * Returns the user name.
     *
     * @return the user name.
     */
    public String getUserRole() {
        return userRole;
    }

    /**
     * Returns the principal name (this method name comes from the JDK {@link Principal} interface).
     *
     * @return the principal name.
     */
    @Override
    public String getName() {
        return userRole;
    }

    /**
     * Returns the authentication mechanism of the token.
     *
     * @return the authentication mechanism of the token.
     */
    public String getSession() {
        return session;
    }

    /**
     * Returns the expiration time of the token.
     *
     * @return the expiration time of the token, in milliseconds since Epoc.
     */
    public long getExpires() {
        return expires;
    }

    /**
     * Returns if the token has expired.
     *
     * @return if the token has expired.
     */
    public boolean isExpired() {
        return getExpires() != -1 && System.currentTimeMillis() > getExpires();
    }

    /**
     * Returns the string representation of the token.
     * 

* This string representation is parseable by the {@link #parse} method. * * @return the string representation of the token. */ @Override public String toString() { return token; } /** * Parses a string into an authentication token. * * @param tokenStr string representation of a token. * * @return the parsed authentication token. * * @throws AuthenticationException thrown if the string representation could not be parsed into * an authentication token. */ public static SaslRoleToken parse(String tokenStr) throws AuthenticationException { Map map = split(tokenStr); if (!map.keySet().equals(ATTRIBUTES)) { throw new AuthenticationException("Invalid token string, missing attributes"); } long expires = Long.parseLong(map.get(EXPIRES)); SaslRoleToken token = new SaslRoleToken(map.get(USER_ROLE), map.get(SESSION)); token.setExpires(expires); return token; } /** * Splits the string representation of a token into attributes pairs. * * @param tokenStr string representation of a token. * * @return a map with the attribute pairs of the token. * * @throws AuthenticationException thrown if the string representation of the token could not be broken into * attribute pairs. */ private static Map split(String tokenStr) throws AuthenticationException { Map map = new HashMap(); StringTokenizer st = new StringTokenizer(tokenStr, ATTR_SEPARATOR); while (st.hasMoreTokens()) { String part = st.nextToken(); int separator = part.indexOf('='); if (separator == -1) { throw new AuthenticationException("Invalid authentication token"); } String key = part.substring(0, separator); String value = part.substring(separator + 1); map.put(key, value); } return map; } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy