有一个修改密码的需求,要求修改完密码之后判断当前用户是否被锁,被锁了的话自动解锁该用户。
weblogic控制台本身有取消用户锁定的功能,但是只能一个一个去解锁,如下图所示:
尝试了2种方式去解锁。第一种是执行java命令,在集群状态下没成功;另一种是用JMX获取MBean来解锁。
一. 使用java命令
这里会用到3条命令:
(1)查找所有Security开头的MBean资源:
java -cp E:\oracle\Middleware\wlserver_12.1\server\lib\weblogic.jar weblogic.Admin -url 192.168.1.199:7001 -username weblogic -password 11111111 query -pretty -pattern Security:*
打开CMD命令行,执行该命令后,会显示MBean Name的列表,如下图所示:
红框圈住的MBeanName就是我要用来解锁的Name,怎么确定是这个MBean呢?
首先,oracleRealm是这台weblogic的默认安全域名,UserLockoutManager是固定名称,oracleRealm+UserLockoutManager自然就是我要找的MBean。
其次,该MBean下列出了一些用户封锁管理统计信息,这些属性值和weblogic控制台的用户封锁管理统计信息是一致的,如下图所示:
(2)查询某个用户是否被锁了:
java -cp E:\oracle\Middleware\wlserver_12.1\server\lib\weblogic.jar weblogic.Admin -url 192.168.1.199:7001 -username weblogic -password 11111111 invoke -mbean Security:Name=oracleRealmUserLockoutManager -method isLockedOut poweruniontest
命令执行后,如果该用户被锁了返回true,否则返回false(我这里是没被锁定的截图),返回结果如下图所示:
(3)解锁:
java -cp E:\oracle\Middleware\wlserver_12.1\server\lib\weblogic.jar weblogic.Admin -url 192.168.1.199:7001 -username weblogic -password 11111111 invoke -mbean Security:Name=oracleRealmUserLockoutManager -method clearLockout poweruniontest
命令执行后,不管该用户是否被锁,都会返回OK,如果命令执行发生错误则会返回failed(未验证),如下图所示:
试验结论:试验证明,在只有一个服务器实例的情况下,这种方法是可以成功解锁的;但是,在集群环境下,比如有一个管理服务器实例(7003)和一个受管服务器实例(8086),不能解锁,其失败表现有三:
1.MBean Name的用户封锁管理统计信息和weblogic控制台的信息不符,一些锁定信息始终为0,如下图所示:
2. 查询用户是否被锁,结果始终返回false。
3.解锁,结果始终返回ok。
原因不明,如有发现,欢迎指正。
二. 使用JMX获取MBean来解锁
1.下面是解锁的封装类:
import java.io.IOException;
import java.net.MalformedURLException;
import java.util.Hashtable;
import javax.management.MBeanServerConnection;
import javax.management.MalformedObjectNameException;
import javax.management.ObjectName;
import javax.management.remote.JMXConnector;
import javax.management.remote.JMXConnectorFactory;
import javax.management.remote.JMXServiceURL;
import javax.naming.Context;
import com.powerunion.oapm.config.ConfigUtil;
public class UnlockWeblogicUser {
public MBeanServerConnection connection;
public JMXConnector connector;
public static final ObjectName service;
public static final String adminServerName;
static{
try {
//Type前面没有空格,若留了空格会报错:
//javax.management.InstanceNotFoundException:
//com.bea:Name=DomainRuntimeService, T
//ype=weblogic.management.mbeanservers.domainruntime.DomainRuntimeServiceMBean
service = new ObjectName("com.bea:Name=DomainRuntimeService,Type=weblogic.management.mbeanservers.domainruntime.DomainRuntimeServiceMBean");
adminServerName = ConfigUtil.getInstance().getParameter("weblogic.security.server.name");
} catch (MalformedObjectNameException e) {
System.out.println("error:"+e.getMessage());
throw new AssertionError(e.getMessage());
}
}
public boolean invoke(String method, String username) {
String rez = "failed";
int index = 0;
try {
System.out.println("About to invoke sericuty method....");
ObjectName[] serverRT =
(ObjectName[]) connection.getAttribute(service,
"ServerRuntimes");
/*
* adminServerName: 在配置文件中配置,集群中管理服务器
*的名称,即负责登录解锁等功能的服务器实例的名称。
*这里对serverRT进行遍历,将管理服务器的索引找出来。
*/
for(int i = 0;i < serverRT.length;i++){
if(serverRT[i].toString().contains(adminServerName)){
index = i;
break;
}
}
ObjectName ssr =
(ObjectName) connection.getAttribute(serverRT[index],
"ServerSecurityRuntime");
ObjectName rrm =
(ObjectName) connection.getAttribute(ssr,
"DefaultRealmRuntime");
ObjectName ulr =
(ObjectName) connection.getAttribute(rrm,
"UserLockoutManagerRuntime");
if(method.equals("isLockedOut")) {
rez =
connection.invoke(ulr, method,
new Object[] {username},
new String[] {"java.lang.String"}).
toString();
} else if(method.equals("clearLockout")) {
connection.invoke(ulr, method,
new Object[] {username},
new String[] {"java.lang.String"});
rez = "OK";
}
System.out.println("User=" + username + " " + method + "=" + rez);
} catch (MalformedURLException exc) {
exc.printStackTrace();
} catch (IOException exc) {
exc.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
try {
connector.close();
} catch (MalformedURLException exc) {
System.out.println(exc.getMessage());
} catch (IOException exc) {
System.out.println(exc.getMessage());
} catch (Exception e) {
System.out.println(e.getMessage());
}
if (rez.trim().equals("false") || rez.trim().equals("failed")) {
return false;
} else {
return true;
}
}
public void initConnection(String hostname, String portString,String username, String password) throws IOException,MalformedURLException{
String protocol = "t3";
Integer portInteger = Integer.valueOf(portString);
int port = portInteger.intValue();
String jndiroot = "/jndi/";
String mserver = "weblogic.management.mbeanservers.domainruntime";
JMXServiceURL serviceURL = new JMXServiceURL(protocol, hostname, port, jndiroot + mserver);
Hashtable<String, String> h = new Hashtable<String, String>();
h.put(Context.SECURITY_PRINCIPAL, username);
h.put(Context.SECURITY_CREDENTIALS, password);
h.put(JMXConnectorFactory.PROTOCOL_PROVIDER_PACKAGES, "weblogic.management.remote");
connector = JMXConnectorFactory.connect(serviceURL, h);
connection = connector.getMBeanServerConnection();
System.out.println("connected!");
}
}
2.下面是调用的类:
//下面的ip、port:管理服务器的ip和端口;username、password:weblogic管理员的用户名和密码。