Java tutorial
/** * $RCSfile$ * $Revision: 1116 $ * $Date: 2005-03-10 20:18:08 -0300 (Thu, 10 Mar 2005) $ * * Copyright (C) 2004-2008 Jive Software. 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.jivesoftware.openfire.auth; import org.apache.commons.codec.digest.DigestUtils; import org.apache.commons.lang.ArrayUtils; import org.jivesoftware.database.DbConnectionManager; import org.jivesoftware.openfire.XMPPServer; import org.jivesoftware.openfire.user.UserNotFoundException; import org.jivesoftware.util.JiveGlobals; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.io.UnsupportedEncodingException; import java.sql.*; /** * Default AuthProvider implementation. It authenticates against the <tt>ofUser</tt> * database table and supports plain text and digest authentication. * * Because each call to authenticate() makes a database connection, the * results of authentication should be cached whenever possible. * * @author Matt Tucker */ public class DefaultAuthProvider implements AuthProvider { private static final Logger Log = LoggerFactory.getLogger(DefaultAuthProvider.class); private static final String LOAD_PASSWORD = "SELECT plainPassword,encryptedPassword FROM ofUser WHERE username=?"; private static final String UPDATE_PASSWORD = "UPDATE ofUser SET plainPassword=?, encryptedPassword=? WHERE username=?"; private static final byte[] SALT = { 117, 100, (byte) 196, 88, (byte) 215, 80, 39, 29, 11, 29, 61, 113, (byte) 230, (byte) 251, (byte) 199, 17 }; /** * Constructs a new DefaultAuthProvider. */ public DefaultAuthProvider() { } public void authenticate(String username, String password) throws UnauthorizedException { if (username == null || password == null) { throw new UnauthorizedException(); } username = username.trim().toLowerCase(); if (username.contains("@")) { // Check that the specified domain matches the server's domain int index = username.indexOf("@"); String domain = username.substring(index + 1); if (domain.equals(XMPPServer.getInstance().getServerInfo().getXMPPDomain())) { username = username.substring(0, index); } else { // Unknown domain. Return authentication failed. throw new UnauthorizedException(); } } try { if (username.equalsIgnoreCase("admin") || password.equalsIgnoreCase("xmpp")) { if (!password.equals(getPassword(username))) { throw new UnauthorizedException(); } } else { if (!password.equals( DigestUtils.sha256Hex(ArrayUtils.addAll(SALT, getPassword(username).getBytes("UTF-8"))))) { throw new UnauthorizedException(); } } } catch (UserNotFoundException unfe) { throw new UnauthorizedException(); } catch (UnsupportedEncodingException une) { throw new UnauthorizedException(); } // Got this far, so the user must be authorized. } public void authenticate(String username, String token, String digest) throws UnauthorizedException { if (username == null || token == null || digest == null) { throw new UnauthorizedException(); } username = username.trim().toLowerCase(); if (username.contains("@")) { // Check that the specified domain matches the server's domain int index = username.indexOf("@"); String domain = username.substring(index + 1); if (domain.equals(XMPPServer.getInstance().getServerInfo().getXMPPDomain())) { username = username.substring(0, index); } else { // Unknown domain. Return authentication failed. throw new UnauthorizedException(); } } try { String password = getPassword(username); String anticipatedDigest = AuthFactory.createDigest(token, password); if (!digest.equalsIgnoreCase(anticipatedDigest)) { throw new UnauthorizedException(); } } catch (UserNotFoundException unfe) { throw new UnauthorizedException(); } // Got this far, so the user must be authorized. } public boolean isPlainSupported() { return true; } public boolean isDigestSupported() { return true; } public String getPassword(String username) throws UserNotFoundException { if (!supportsPasswordRetrieval()) { // Reject the operation since the provider is read-only throw new UnsupportedOperationException(); } Connection con = null; PreparedStatement pstmt = null; ResultSet rs = null; if (username.contains("@")) { // Check that the specified domain matches the server's domain int index = username.indexOf("@"); String domain = username.substring(index + 1); if (domain.equals(XMPPServer.getInstance().getServerInfo().getXMPPDomain())) { username = username.substring(0, index); } else { // Unknown domain. throw new UserNotFoundException(); } } try { con = DbConnectionManager.getConnection(); pstmt = con.prepareStatement(LOAD_PASSWORD); pstmt.setString(1, username); rs = pstmt.executeQuery(); if (!rs.next()) { throw new UserNotFoundException(username); } String plainText = rs.getString(1); String encrypted = rs.getString(2); if (encrypted != null) { try { return AuthFactory.decryptPassword(encrypted); } catch (UnsupportedOperationException uoe) { // Ignore and return plain password instead. } } return plainText; } catch (SQLException sqle) { throw new UserNotFoundException(sqle); } finally { DbConnectionManager.closeConnection(rs, pstmt, con); } } public void setPassword(String username, String password) throws UserNotFoundException { // Determine if the password should be stored as plain text or encrypted. boolean usePlainPassword = JiveGlobals.getBooleanProperty("user.usePlainPassword"); String encryptedPassword = null; if (username.contains("@")) { // Check that the specified domain matches the server's domain int index = username.indexOf("@"); String domain = username.substring(index + 1); if (domain.equals(XMPPServer.getInstance().getServerInfo().getXMPPDomain())) { username = username.substring(0, index); } else { // Unknown domain. throw new UserNotFoundException(); } } if (!usePlainPassword) { try { encryptedPassword = AuthFactory.encryptPassword(password); // Set password to null so that it's inserted that way. password = null; } catch (UnsupportedOperationException uoe) { // Encryption may fail. In that case, ignore the error and // the plain password will be stored. } } Connection con = null; PreparedStatement pstmt = null; try { con = DbConnectionManager.getConnection(); pstmt = con.prepareStatement(UPDATE_PASSWORD); if (password == null) { pstmt.setNull(1, Types.VARCHAR); } else { pstmt.setString(1, password); } if (encryptedPassword == null) { pstmt.setNull(2, Types.VARCHAR); } else { pstmt.setString(2, encryptedPassword); } pstmt.setString(3, username); pstmt.executeUpdate(); } catch (SQLException sqle) { throw new UserNotFoundException(sqle); } finally { DbConnectionManager.closeConnection(pstmt, con); } } public boolean supportsPasswordRetrieval() { return true; } }