001/* 002 * Copyright 2012 Atteo. 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016package org.atteo.moonshine.shiro.database; 017 018import org.apache.shiro.authc.AuthenticationException; 019import org.apache.shiro.authc.AuthenticationInfo; 020import org.apache.shiro.authc.AuthenticationToken; 021import org.apache.shiro.authc.SimpleAuthenticationInfo; 022import org.apache.shiro.authc.credential.HashedCredentialsMatcher; 023import org.apache.shiro.codec.Hex; 024import org.apache.shiro.crypto.RandomNumberGenerator; 025import org.apache.shiro.crypto.SecureRandomNumberGenerator; 026import org.apache.shiro.crypto.hash.SimpleHash; 027import org.apache.shiro.realm.AuthenticatingRealm; 028import org.apache.shiro.subject.SimplePrincipalCollection; 029import org.apache.shiro.util.ByteSource; 030import org.apache.shiro.util.SimpleByteSource; 031 032import com.google.inject.Inject; 033 034public class DatabaseRealm extends AuthenticatingRealm { 035 private final int hashIterations = 1536; 036 private final String hashAlgorithm = "SHA-256"; 037 private final RandomNumberGenerator randomNumberGenerator; 038 039 @Inject 040 private AccountRepository accountRepository; 041 042 public DatabaseRealm() { 043 this.randomNumberGenerator = new SecureRandomNumberGenerator(); 044 045 HashedCredentialsMatcher credentialsMatcher = new HashedCredentialsMatcher(hashAlgorithm); 046 credentialsMatcher.setHashIterations(hashIterations); 047 setCredentialsMatcher(credentialsMatcher); 048 049 setName("LoginRealm"); 050 } 051 052 public int getHashIterations() { 053 return hashIterations; 054 } 055 056 public String getHashAlgorithm() { 057 return hashAlgorithm; 058 } 059 060 public ByteSource generateSalt() { 061 return randomNumberGenerator.nextBytes(); 062 } 063 064 public String hashPassword(String password, ByteSource salt) { 065 return new SimpleHash(hashAlgorithm, password, salt, hashIterations).toHex(); 066 } 067 068 @Override 069 protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) 070 throws AuthenticationException { 071 String principal = (String) token.getPrincipal(); 072 Account loginAccount = accountRepository.findOne(principal); 073 074 if (loginAccount == null) { 075 return null; 076 } 077 078 SimplePrincipalCollection principalCollection = new SimplePrincipalCollection( 079 loginAccount.getLogin(), getName()); 080 081 SimpleAuthenticationInfo info = new SimpleAuthenticationInfo(principalCollection, 082 loginAccount.getHashedPassword(), new SimpleByteSource(Hex.decode(loginAccount 083 .getSalt()))); 084 085 return info; 086 } 087}