/** * Copyright 2014 Lockheed Martin Corporation * * 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 streamflow.server.security; import com.google.inject.Inject; import streamflow.model.Role; import streamflow.model.User; import streamflow.service.RoleService; import streamflow.service.UserService; import org.apache.shiro.authc.AuthenticationException; import org.apache.shiro.authc.AuthenticationInfo; import org.apache.shiro.authc.AuthenticationToken; import org.apache.shiro.authc.SimpleAccount; import org.apache.shiro.authc.UsernamePasswordToken; import org.apache.shiro.authc.credential.CredentialsMatcher; import org.apache.shiro.authz.AuthorizationException; import org.apache.shiro.authz.AuthorizationInfo; import org.apache.shiro.authz.SimpleAuthorizationInfo; import org.apache.shiro.realm.AuthorizingRealm; import org.apache.shiro.subject.PrincipalCollection; import org.apache.shiro.subject.SimplePrincipalCollection; import org.apache.shiro.util.SimpleByteSource; import org.slf4j.Logger; import org.slf4j.LoggerFactory; public class DatastoreRealm extends AuthorizingRealm { protected static final Logger LOG = LoggerFactory.getLogger(DatastoreRealm.class); private final UserService userService; private final RoleService roleService; private final CredentialsMatcher credentialsMatcher; @Inject public DatastoreRealm(UserService userService, RoleService roleService, CredentialsMatcher credentialsMatcher) { this.userService = userService; this.roleService = roleService; this.credentialsMatcher = credentialsMatcher; } @Override public CredentialsMatcher getCredentialsMatcher() { return credentialsMatcher; } @Override protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException { // Make sure the token is of the property type if (!(token instanceof UsernamePasswordToken)) { //LOG.error("The provided token is not a UsernamePasswordToken"); throw new AuthenticationException( "The provided token is not a UsernamePasswordToken"); } // Retrieve the username from the token UsernamePasswordToken usernamePasswordToken = (UsernamePasswordToken) token; String username = usernamePasswordToken.getUsername(); if (username == null) { //LOG.error("The provided token does not contain a username"); throw new AuthenticationException( "The provided token does not contain a username"); } User user = getUserByUsernameOrEmail(username); if (user == null) { LOG.warn("User with the specified username does not exist: " + username); throw new AuthenticationException("The username/password was invalid"); } // Make sure the user account is enabled if (!user.getEnabled()) { //LOG.error("User account with the specified username is disabled: {}", username); throw new AuthenticationException("The user account is disabled"); } // Generate the authentication info using the passsword and salt SimpleAccount info = new SimpleAccount(username, user.getPassword(), new SimpleByteSource(user.getPasswordSalt()), getName()); // Associate the principals with the authentication info SimplePrincipalCollection principals = new SimplePrincipalCollection(); principals.add(user.getId(), getName()); principals.add(user.getUsername(), getName()); principals.add(user.getEmail(), getName()); info.setPrincipals(principals); return info; } @Override protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) { if (principalCollection == null) { //LOG.error("The provided PrincipalCollection is null"); return null; } Object principalId = getAvailablePrincipal(principalCollection); if (principalId == null) { //LOG.error("The provided PrincipalCollection does not have any available principals"); return null; } User user = getUserByUsernameOrEmail((String) principalId); if (user == null) { //LOG.error("User with the specified username/email does not exist: " + principalId); throw new AuthorizationException( "User with the specified username/email does not exist: " + principalId); } // Build the authorization info using the roles for the specified user SimpleAuthorizationInfo info = new SimpleAuthorizationInfo(); for (String userRole : user.getRoles()) { // Associate the role with the current principal info.addRole(userRole); Role role = roleService.getRole(userRole); // Add all of the permissions for the specified role info.addStringPermissions(role.getPermissions()); } return info; } private User getUserByUsernameOrEmail(String username) { User user = userService.getUserByUsername(username); if (user == null) { user = userService.getUserByEmail(username); if (user == null) { try { user = userService.getUser(username); } catch (Exception ex) { user = null; } } } return user; } public void destroy() { // TODO: Cleanup any resources that are necessary before shutdown } }