Java tutorial
/* * Copyright (c) 2012, Paul Merlin. All Rights Reserved. * * 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 org.qi4j.library.shiro.domain.passwords; import java.util.Set; import org.apache.shiro.authc.AuthenticationException; import org.apache.shiro.authc.AuthenticationInfo; import org.apache.shiro.authc.AuthenticationToken; import org.apache.shiro.authc.SimpleAuthenticationInfo; import org.apache.shiro.authc.UsernamePasswordToken; import org.apache.shiro.authc.credential.DefaultPasswordService; import org.apache.shiro.authc.credential.PasswordMatcher; import org.apache.shiro.authc.credential.PasswordService; import org.apache.shiro.authz.AuthorizationInfo; import org.apache.shiro.authz.Authorizer; import org.apache.shiro.authz.SimpleAuthorizationInfo; import org.apache.shiro.crypto.hash.DefaultHashService; import org.apache.shiro.realm.AuthorizingRealm; import org.apache.shiro.realm.Realm; import org.apache.shiro.subject.PrincipalCollection; import org.qi4j.api.configuration.Configuration; import org.qi4j.api.injection.scope.Structure; import org.qi4j.api.injection.scope.This; import org.qi4j.api.query.QueryBuilder; import org.qi4j.api.service.ServiceActivation; import org.qi4j.api.structure.Module; import org.qi4j.api.unitofwork.UnitOfWork; import org.qi4j.library.shiro.Shiro; import org.qi4j.library.shiro.domain.permissions.RoleAssignee; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import static org.qi4j.api.query.QueryExpressions.eq; import static org.qi4j.api.query.QueryExpressions.templateFor; public class PasswordRealmMixin extends AuthorizingRealm implements Realm, Authorizer, PasswordService, ServiceActivation { private static final Logger LOG = LoggerFactory.getLogger(Shiro.LOGGER_NAME); @Structure private Module module; @This private Configuration<PasswordRealmConfiguration> configuration; private final DefaultPasswordService passwordService; public PasswordRealmMixin() { super(); passwordService = new DefaultPasswordService(); PasswordMatcher matcher = new PasswordMatcher(); matcher.setPasswordService(passwordService); setCredentialsMatcher(matcher); } @Override public void activateService() throws Exception { configuration.refresh(); PasswordRealmConfiguration config = configuration.get(); String algorithm = config.hashAlgorithmName().get(); Integer iterations = config.hashIterationsCount().get(); if (algorithm != null || iterations != null) { DefaultHashService hashService = (DefaultHashService) passwordService.getHashService(); if (algorithm != null) { hashService.setHashAlgorithmName(algorithm); } if (iterations != null) { hashService.setHashIterations(iterations); } } } @Override public void passivateService() throws Exception { } @Override public String encryptPassword(Object plaintextPassword) throws IllegalArgumentException { return passwordService.encryptPassword(plaintextPassword); } @Override public boolean passwordsMatch(Object submittedPlaintext, String encrypted) { return passwordService.passwordsMatch(submittedPlaintext, encrypted); } @Override protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException { UnitOfWork uow = module.newUnitOfWork(); try { String username = ((UsernamePasswordToken) token).getUsername(); PasswordSecurable account = findPasswordSecurable(uow, username); if (account == null) { LOG.debug("Unknown subject identifier: {}" + username); return null; } LOG.debug("Found account for {}: {}", username, account); return new SimpleAuthenticationInfo(account.subjectIdentifier().get(), account.password().get(), getName()); } finally { uow.discard(); } } @Override protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) { UnitOfWork uow = module.newUnitOfWork(); try { String username = getAvailablePrincipal(principals).toString(); RoleAssignee roleAssignee = findRoleAssignee(uow, username); if (roleAssignee == null) { LOG.debug("No authorization info for {}", username); return null; } LOG.debug("Found role assignee for {}: {}", username, roleAssignee); Set<String> roleNames = roleAssignee.roleNames(); Set<String> permissionStrings = roleAssignee.permissionStrings(); LOG.debug("Found role assignee has the following roles: {}", roleNames); LOG.debug("Found role assignee has the following permissions: {}", permissionStrings); SimpleAuthorizationInfo atzInfo = new SimpleAuthorizationInfo(roleNames); atzInfo.setStringPermissions(permissionStrings); return atzInfo; } finally { uow.discard(); } } private PasswordSecurable findPasswordSecurable(UnitOfWork uow, String username) { QueryBuilder<PasswordSecurable> builder = module.newQueryBuilder(PasswordSecurable.class); builder = builder.where(eq(templateFor(PasswordSecurable.class).subjectIdentifier(), username)); return uow.newQuery(builder).find(); } private RoleAssignee findRoleAssignee(UnitOfWork uow, String username) { QueryBuilder<RoleAssignee> builder = module.newQueryBuilder(RoleAssignee.class); builder = builder.where(eq(templateFor(RoleAssignee.class).subjectIdentifier(), username)); return uow.newQuery(builder).find(); } }