您的位置:首页 > 运维架构

OpenFire源码学习之二十一:openfie对用户的优化(上)

2015-02-03 21:58 281 查看

用户类

优化用户主要是要解决用户的连接量。已经对用户的访问速度和吞吐量。

预初始化

在前面的带面中提出来了用户的预初始化。这里就不在贴出来了。下面将redis用户库连接池处理贴出来UserJedisPoolManager

public class UserJedisPoolManager extends BasicModule{

private static final Logger log = LoggerFactory.getLogger(UserJedisPoolManager.class);

private static final String OF_ALL_USER = "select username, encryptedPassword, name, email, moblie, creationDate, modificationDate from ofuser";
private static final String OF_USER_VCARD = "select username, vcard from ofvcard";
private static final String OF_PRESENCE = "select username, offlinePresence, offlineDate from ofPresence";

//private static final String REDIS_USER = "REDIS_USER";
private static final Integer timeout = 1000*10;
private static final int maxActive = 5000 * 10;
private static final int maxIdle = 50;
private static final long maxWait = (1000 * 100);

private static JedisPool pool;
private static XMPPServer loaclserver;
private static JedisPoolConfig configs;

public UserJedisPoolManager() {
super("User redis manager");
}

private static JedisPoolConfig createConfig() {
configs = new JedisPoolConfig();
configs.setMaxActive(maxActive);
configs.setMaxIdle(maxIdle);
configs.setMaxWait(maxWait);
configs.setTestOnBorrow(false);
return configs;
}

private void createJedisPool() {
RedisConfig redisConfig = loaclserver.getJedisConfDao().getRedisConfig("REDIS_USER");
if (redisConfig != null) {
+ " ,auto:" + redisConfig.getAuto());
System.out.println(redisConfig.getAuto() .equals("") );
pool = new JedisPool(createConfig(), redisConfig.getIp(), Integer.valueOf(redisConfig.getPort().trim()),
timeout, redisConfig.getAuto().equals("")  ? null : redisConfig.getAuto());
Jedis jedis = pool.getResource();
jedis.select(0);
if(!jedis.exists("OFUSER:admin")) {
DefaultAuthProvider dup = new DefaultAuthProvider();
try {
String password = dup.getPassword("admin");
password = AuthFactory.encryptPassword(password);
Map<String, String> map = new HashMap<String, String>();
map.put("NAME", "admin");
map.put("PASSWORD", password);
map.put("CREATIONDATE", "0");
map.put("MODIFICATIONDATE", "0");
jedis.hmset("OFUSER:admin", map);
} catch (UserNotFoundException e) {
e.printStackTrace();
}finally{
pool.returnResource(jedis);
}			}
}
}

private void poolInit() {
createJedisPool();
}

public Jedis getJedis() {
if (pool == null)
{
poolInit();
}
Jedis jedis = pool.getResource();
jedis.select(0);
return jedis;
}

public void returnRes(Jedis jedis) {
pool.returnResource(jedis);
}

@Override
public void initialize(XMPPServer server) {
super.initialize(server);
loaclserver = server;
poolInit();
log.info("UserManager By Redis: start init....");

}

public Collection<User> getAllUser() {
Collection<User> users = new ArrayList<User>();
PreparedStatement pstmt = null;
Connection con = null;
ResultSet rs = null;
try {
con = (Connection) DbConnectionManager.getConnection();
pstmt = con.prepareStatement(OF_ALL_USER);
rs = pstmt.executeQuery();
while(rs.next()) {
User user = new User();
user.setUsername(rs.getString(1));
user.setPassword(rs.getString(2));
user.setName(rs.getString(3));
user.setEmail(rs.getString(4));
user.setMoblie(rs.getString(5));
user.setCreationDate(rs.getString(6));
user.setModificationDate(rs.getString(7));
users.add(user);
}
}catch (Exception e) {
log.info( e.getMessage());
e.printStackTrace();
}
finally {
DbConnectionManager.closeConnection(pstmt, con);
}
return users;
}

public Collection<UserVcard> getUserVcard() {
Collection<UserVcard> userVcards = new ArrayList<UserVcard>();
PreparedStatement pstmt = null;
Connection con = null;
ResultSet rs = null;
try {
con = (Connection) DbConnectionManager.getConnection();
pstmt = con.prepareStatement(OF_USER_VCARD);
rs = pstmt.executeQuery();
while(rs.next()) {
UserVcard user = new UserVcard();
user.setUsername(rs.getString(1));
user.setVcard(rs.getString(2));
userVcards.add(user);
}
}catch (Exception e) {
log.info( e.getMessage());
e.printStackTrace();
}
finally {
DbConnectionManager.closeConnection(pstmt, con);
}
return userVcards;
}

public Collection<Presence> getPresences() {
......
}
}


在上面createJedisPool方法中预置了管理员的账号。这是因为我们需要修改openfire的用户认证dao。也就是说web控制台的管理员。在登陆web页面的时候,我们认证也是先走redis验证的。

用户认证

用户认证,首先需要重新实现AuthProvider。Openfire当中默认使用的是DefaultAuthProvider来操作数据层。当然他也提供了其他的方式实现接口,比如:HybridAuthProvider、JDBCAuthProvider、NativeAuthProvider、POP3AuthProvider等。

写完AuthProvider的Redis实现后,接下来需要基于Redis的用户DAO。

下面是两个类的源码清单:

RedisAuthProvider

public class RedisAuthProvider implements AuthProvider{

private static final Logger log = LoggerFactory.getLogger(RedisAuthProvider.class);
private static HmThreadPool threadPool = new HmThreadPool(3);
......

@Override
public void authenticate(String username, String password)
throws UnauthorizedException, ConnectionException,
InternalUnauthenticatedException {
......
}

@Override
public void authenticate(String username, String token, String digest)
throws UnauthorizedException, ConnectionException,
InternalUnauthenticatedException {
......
}

@Override
public String getPassword(String username) throws UserNotFoundException,
UnsupportedOperationException {
Jedis jedis = XMPPServer.getInstance().getUserJedis().getJedis();
try {
String pw = jedis.hmget("OFUSER:" + username, "PASSWORD").get(0);
if (pw == null) {
String userid = jedis.get("MOBILE:" + username);
pw = jedis.hmget("OFUSER:" + userid, "PASSWORD").get(0);
}
return AuthFactory.decryptPassword(pw);
} finally {
XMPPServer.getInstance().getUserJedis().returnRes(jedis);
}
}

@Override
public void setPassword(String username, String password)
throws UserNotFoundException, UnsupportedOperationException {
Jedis jedis = XMPPServer.getInstance().getUserJedis().getJedis();
try {
password = AuthFactory.encryptPassword(password);
jedis.hset("OFUSER:" + username, "PASSWORD", password);
} finally {
XMPPServer.getInstance().getUserJedis().returnRes(jedis);
}
threadPool.execute(createTask(XMPPServer.getInstance().getJedisConfDao().getAuthProvider(), username, password));
}

@Override
public boolean supportsPasswordRetrieval() {
// TODO Auto-generated method stub
return true;
}

private static final String UPDATE_PASSWORD =
"UPDATE ofUser SET encryptedPassword=? WHERE username=?";

private Runnable createTask(final AuthProvider edp, final String username,
final String password) {
return new Runnable() {
public void run() {
try {
//edp.setPassword(username, password);

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);
}
pstmt.setString(2, username);
pstmt.executeUpdate();
}
catch (SQLException sqle) {
throw new UserNotFoundException(sqle);
}
finally {
DbConnectionManager.closeConnection(pstmt, con);
}

} catch (UserNotFoundException e) {
log.info("UserNotFoundException: " + username);
}
}
};
}
}

用户认证写完后,要记得修改系统属性表:ofProperty

provider.auth.className

org.jivesoftware.util.redis.expand.RedisAuthProvider

RedisUserProvider:

public class RedisUserProvider implements UserProvider{
......
public User loadUser(String username) throws UserNotFoundException {
if(username.contains("@")) {
if (!XMPPServer.getInstance().isLocal(new JID(username))) {
throw new UserNotFoundException("Cannot load user of remote server: " + username);
}
username = username.substring(0,username.lastIndexOf("@"));
}

Jedis jedis = XMPPServer.getInstance().getUserJedis().getJedis();

try {
Map<String, String> map = jedis.hgetAll("OFUSER:" + username);
String usernames = username;
if (map.isEmpty()) {
String userid = jedis.get("OFUSER:" + username);
map = jedis.hgetAll("OFUSER:" + userid);
if (map.isEmpty()) {
return XMPPServer.getInstance().getJedisConfDao().getUserProvider().loadUser(username);
}
usernames = userid;
}
String name = map.get("NAME");
String email = map.get("EMAIL");
String mobile = map.get("MOBILE");
String creationDate = map.get("CREATIONDATE");
String modificationDate = map.get("MODIFICATIONDATE");

User user = new User(usernames, name, email, mobile, new Date(Long.parseLong(creationDate.equals("0")||creationDate.equals("") ? StringUtils.dateToMillis(new Date()) : creationDate)),
new Date(Long.parseLong(modificationDate.equals("0")||modificationDate.equals("") ? StringUtils.dateToMillis(new Date()) : modificationDate)));

return user;

} finally {
XMPPServer.getInstance().getUserJedis().returnRes(jedis);
}

}

public User createUser(String username, String password, String name, String email)
throws UserAlreadyExistsException
{
return createUser(username, password, name, email, null);
}

public User createUser(String username, String password, String name, String email, String moblie)
throws UserAlreadyExistsException{
try {
loadUser(username);
// The user already exists since no exception, so:
throw new UserAlreadyExistsException("Username " + username + " already exists");
}
catch (UserNotFoundException unfe) {

Jedis jedis = XMPPServer.getInstance().getUserJedis().getJedis();

Map<String, String> hash = new HashMap<String, String>();

password = AuthFactory.encryptPassword(password);

hash.put("PASSWORD", password);
if (name != null && !"".equals(name))
hash.put("NAME", name);
if (email != null && !"".equals(email))
hash.put("EMAIL", email);
if (moblie != null && !"".equals(moblie))
hash.put("MOBILE", moblie);

Date now = new Date();
hash.put("CREATIONDATE", StringUtils.dateToMillis(now));
hash.put("MODIFICATIONDATE", StringUtils.dateToMillis(now));

try {
jedis.hmset("OFUSER:" + username, hash);
} finally {
XMPPServer.getInstance().getUserJedis().returnRes(jedis);
}

threadPool.execute(createTaskAddUser(username, null, password, name, email, moblie));
return new User(username, name, email, moblie, now, now);
}
}

private Runnable createTaskAddUser(final String username, final String password, final String encryptedPassword,
final String name, final String email, final String moblie) {
return new Runnable() {
public void run () {
.....
}
};
}

public void deleteUser(String username) {
......
}

public int getUserCount() {
int count = 0;
Connection con = null;
PreparedStatement pstmt = null;
ResultSet rs = null;
try {
con = DbConnectionManager.getConnection();
pstmt = con.prepareStatement(USER_COUNT);
rs = pstmt.executeQuery();
if (rs.next()) {
count = rs.getInt(1);
}
}
catch (SQLException e) {
Log.error(e.getMessage(), e);
}
finally {
DbConnectionManager.closeConnection(rs, pstmt, con);
}
return count;
}

public Collection<User> getUsers() {
Collection<String> usernames = getUsernames(0, Integer.MAX_VALUE);
return new UserCollection(usernames.toArray(new String[usernames.size()]));
}

public Collection<String> getUsernames() {
return getUsernames(0, Integer.MAX_VALUE);
}

private Collection<String> getUsernames(int startIndex, int numResults) {
......
}

public Collection<User> getUsers(int startIndex, int numResults) {
Collection<String> usernames = getUsernames(startIndex, numResults);
return new UserCollection(usernames.toArray(new String[usernames.size()]));
}

public void setName(String username, String name) throws UserNotFoundException {
......
}

public void setEmail(String username, String email) throws UserNotFoundException {
......
}

public void setCreationDate(String username, Date creationDate) throws UserNotFoundException {
......
}

public void setModificationDate(String username, Date modificationDate) throws UserNotFoundException {
......
}

public Set<String> getSearchFields() throws UnsupportedOperationException {
return new LinkedHashSet<String>(Arrays.asList("Username", "Name", "Email"));
}

public Collection<User> findUsers(Set<String> fields, String query) throws UnsupportedOperationException {
return findUsers(fields, query, 0, 100);
}

public Collection<User> findUsers(Set<String> fields, String query, int startIndex,
int numResults) throws UnsupportedOperationException
{
......
}
/**
* Make sure that Log.isDebugEnabled()==true before calling this method.
* Twenty elements will be logged in every log line, so for 81-100 elements
* five log lines will be generated
* @param listElements a list of Strings which will be logged
*/
private void LogResults(List<String> listElements) {
......
}

@Override
public void setMoblie(String username, String moblie)
throws UserNotFoundException {
......
}
}

注意:这里有个moblie字段。在原来openfire用户认证表里面是没有这个字段的。这里是本人新加的字段。方便手机登陆。看各自的页面场景啦。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: