/* Copyright (c) 2011 Danish Maritime Authority.
*
* Licensed 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 net.maritimecloud.mms.server.security;
import javax.servlet.http.HttpServletRequest;
import javax.websocket.Session;
import java.util.Objects;
/**
* <p>The {@code Subject} is - up to a point - modelled on the
* <a href="http://shiro.apache.org/static/latest/apidocs/org/apache/shiro/subject/Subject.html">
* Apache Shiro Subject</a> concept.
* </p>
* <p>
* A {@code Subject} encapsulates the identity and state of the current client. It contains
* methods for logging the client in and out.
* </p>
* The {@code Subject} should be instantiated in the websocket {@code @OnOpen} method using the
* {@code SecurityManager} class.
*
*/
public interface Subject {
/**
* Returns the Principal associated with the subject
* @return the principal
*/
Object getPrincipal();
/**
* Returns whether the subject has been authenticated
* @return whether the subject has been authenticated
*/
boolean isAuthenticated();
/**
* Asserts that the client maritime ID is valid for this Subject by returning quietly if they do or throwing n
* {@link ClientVerificationException} if they do not.
*
* @param clientId the maritime ID of the client.
* @throws ClientVerificationException if the client is not valid for this Subject.
*/
void checkClient(String clientId) throws ClientVerificationException;
/**
* Logs in the current subject using the given authentication token.
* If the login attempt fails, an exception is thrown.
*
* @param token authentication token.
*/
void login(AuthenticationToken token) throws AuthenticationException;
/**
* Logs out the Subject
*/
void logout();
/**
* Builds a {@link Subject} from either a WebSocket Session or a
* from a http servlet request.
*/
class Builder {
/** The security manager */
private final MmsSecurityManager securityManager;
/** The websocket session */
private Session session;
/** The http servlet request - used for REST security **/
private HttpServletRequest request;
/**
* Instantiates the builder with the MMS security manager
* @param securityManager the MMS security manager
*/
public Builder(MmsSecurityManager securityManager) {
Objects.requireNonNull(securityManager);
this.securityManager = securityManager;
}
public Builder setSession(Session session) {
if (request != null) {
throw new IllegalArgumentException("Subject must be built from either a WebSocket session or a servlet request, not both");
}
this.session = session;
return this;
}
public Builder setRequest(HttpServletRequest request) {
if (session != null) {
throw new IllegalArgumentException("Subject must be built from either a WebSocket session or a servlet request, not both");
}
this.request = request;
return this;
}
public Subject build() {
if (request == null && session == null) {
throw new IllegalArgumentException("Subject must be built from either a WebSocket session or a servlet request");
} else if (request != null) {
return securityManager.instantiateSubject(request);
} else {
return securityManager.instantiateSubject(session);
}
}
}
}