Java program to change Active Directory user password (over SSL)?
Note, that to change Active Directory user password, connection must be made over SSL.
To enable SSL on Active Directory, and get hold of ssl certificate, see instructions for that here.
The program:
import javax.naming.*;
import javax.naming.directory.*;
import javax.naming.ldap.*;
import java.util.*;
import java.security.*;
public class ADPasswdChange {
DirContext ldapContext;
String baseName = ",CN=Users,DC=mydomain,DC=local";
String serverIP = "localhost";
public ADPasswdChange() {
try {
Hashtable env = new Hashtable();
env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory");
env.put(Context.SECURITY_AUTHENTICATION, "Simple");
//NOTE: Replace the user and password in next two lines, this user should have privileges to change password.
//NOTE: This is NOT the user whose password is being changed.
env.put(Context.SECURITY_PRINCIPAL, "powerfuluser@mydomain.local");
env.put(Context.SECURITY_CREDENTIALS, "whateverpassword");
//NOTE: Replace localhost in next line with actual ldap host:
env.put(Context.PROVIDER_URL, "ldap://localhost:636");
env.put(Context.SECURITY_PROTOCOL, "ssl");
ldapContext = new InitialLdapContext(env, null);
}
catch (Exception e) {
System.out.println(" bind error: " + e);
e.printStackTrace();
System.exit(-1);
}
}
public void updatePassword(String username, String password) {
try {
System.out.println("1");
String quotedPassword = "\"" + password + "\"";
char unicodePwd[] = quotedPassword.toCharArray();
byte pwdArray[] = new byte[unicodePwd.length * 2];
for (int i=0; i<unicodePwd.length; i++) {
pwdArray[i*2 + 1] = (byte) (unicodePwd[i] >>> 8);
pwdArray[i*2 + 0] = (byte) (unicodePwd[i] & 0xff);
}
ModificationItem[] mods = new ModificationItem[1];
mods[0] = new ModificationItem(DirContext.REPLACE_ATTRIBUTE,
new BasicAttribute("UnicodePwd", pwdArray));
ldapContext.modifyAttributes("CN=" + username + baseName, mods);
}
catch (Exception e) {
System.out.println("update password error: " + e);
System.exit(-1);
}
}
public static void main(String[] args) {
Security.addProvider(new com.sun.net.ssl.internal.ssl.Provider());
// the keystore that holds trusted root certificates
//NOTE: Replace with path to ssl certificate keystore file below.
System.setProperty("javax.net.ssl.trustStore", "C:/mydir/keystore.jks");
//NOTE: Replace with keystore password that was used while converting .cer to .jks file.
System.setProperty("javax.net.ssl.trustStorePassword", "thekeypasswd");
System.setProperty("javax.net.debug", "all");
ADPasswdChange adc = new ADPasswdChange();
//NOTE: Replace below with username whose password has to be changed and the desired password.
adc.updatePassword("user1", "change$2pass");
}
}
The above program is a slightly modified version of the one mentioned here:
http://blogs.msdn.com/b/alextch/archive/2012/05/15/how-to-set-active-directory-password-from-java-application.aspx
How to configure SSL on Active Directory?
Assuming Active Directory is already setup. See instructions for that here.
Enable Active Directory Certificate Services
- Open Server Manager
- Add Role
- Choose Active Directory Certificate Services.
Certificates
- Open MMC
- File> Add/Remove Snap-In
- Choose ‘Certificates’ > ‘Local Computer’
- Once added, right-click on Certificates> All Tasks > Request New Certificate > Active Directory Enrollment Policy > Select Domain Controller, Domain Controller Authentication checkboxes> Enroll
Note that, in the same MMC, following Snap-Ins were also added, not sure if they are needed though:
- Certification Authority (Local)
- Certification Service (Active Dir Domain Services)
- Certification Service (Active Dir Certificate Services)
Test
- Start> Run> ldp.exe
- Connect with SSL and port 636
Export Certificate (for use with Client)
- On a Domain Controller log-in as an administrator and open Internet Explorer. Go to Tools->Internet Options->Content and click on Certificate
- Switch to Trusted Root Certificate Authorities Tab and Select the certificate issued by your Active Directory integrated Certificate Server. Click on Export
- Choose Base-64 encoded X.509(.CER)
- Specify file name for the exported certificate
- Finish the export and copy the exported .cer file
Using the exported certificate with Java client application:
- Copy .cer file exported above to the java client machine
- At the client machine execute the following command:
keytool -importcert -file cert.cer -keystore keystore.jks -alias “Alias”
Give a password when prompted.
This will create a .jks file that you can use with your java client program for ssl communication with Active Directory.
References:
http://blogs.msdn.com/b/alextch/archive/2012/05/15/how-to-set-active-directory-password-from-java-application.aspx
http://www.christowles.com/2010/11/enable-ldap-over-ssl-ldaps-on-windows.html
How to setup Active Directory on Windows Server?
Machine used: Windows 2008 Server Base 2
Setup Active Directory
Active Directory Domain Services
- Open Server Manager
- Click Add Role link on the right-hand pane.
- Choose Active Directory Domain Services.
DNS Server
- Open Server Manager
- Click Add Role link on the right-hand pane.
- Choose DNS Server.
Active Directory Administrative Center
- Open Active Directory Administrative Center
- Add user.
Test
- Start> Run> ldp.exe
- Connect
Which (java) thread is consuming maximum CPU?
Problem Statement
Your java application it utilizing very high cpu (eg: 100%), you do not know which java thread is causing this. In Java Web Application which is a multi-threaded environment, it becomes important to know this. Thread Dumps tell us what the threads are doing, but they do not tell us which thread is utilizing the maximum CPU.
Solution
On Linux, following commands will help us:
top command can tell us which (java or any) process is utilizing how much CPU
top -H command gives similar output, but this time by Linux Threads (instead of Processes), so from here we can determine the thread id that is using large cpu. But remember this thread id is decimal notation, while jstack output (thread dump) has thread id in hexadecimal so a conversion from decimal to hexadecimal is needed, before you can locate the offending thread in thread dump (the ‘nid’ field in thread dump corresponds to it).
On Linux you can convert decimal to hex as follows:
$ printf '%x' 65332
7541
Here is what your a contents of Thread Dump looks like (see the nid=0×7541 below):
'Busy' prio=10 tid=0x8f3cf400 nid=0x7541 runnable [0x3f25b120] java.lang.Thread.State: RUNNABLE at java.something.do(Whatever.java:114)
Ref:
http://www.javacodegeeks.com/2012/08/which-java-thread-consumes-my-cpu.html
How to convert a Project in Eclipse IDE to Java Project?
- Select project.
- Open the project properties via Project > Properties.
- Choose “Targetted Runtimes” on left, and add the proper runtime. Click apply.
- Choose “Project Facets” on left, and select the JAVA facet which should have appeared due to previous step. Click apply.
Space in LDAP SSL URL causes: ‘MalformedURLException: Invalid URI:’
Problem Statement:
You are trying to connect to LDAP(SSL) from a Java Program as follows:
...
prop.put(Context.INITIAL_CONTEXT_FACTORY,"com.sun.jndi.ldap.LdapCtxFactory");
...
prop.put(Context.PROVIDER_URL, "ldap://host:636/OU=My Org,DC=domain,DC=com");
LdapContext ctx =new InitialLdapContext(prop,null);
...
And you see error message like:
MalformedURLException: Invalid URI: Invalid URI: Org,DC=domain,DC=com]
Solution
This error is caused by the space in URI. So in this case space in: ‘My Org’ part of the URL.
If you replace ‘My Org’ with ‘My%20Org’, the error should go away.
So, your code should now look like:
...
prop.put(Context.PROVIDER_URL, "ldap://host:636/OU=My%20Org,DC=domain,DC=com");
...
Oracle Query Optimization Tips
Why is my Query Slow?
You can easily examine where your query is spending time by enabling autotracing, and reviewing the results
Set Autotrace ON
Now Execute your Query (lets say it is a DELETE Query), and look at the results.
Your results will look something like this:
Plan hash value: 2130017389
—————————————————————————————————-
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
—————————————————————————————————-
| 0 | DELETE STATEMENT | | 49 | 2291 | 41 (0)| 00:00:01 |
| 1 | DELETE | WHATEVER_TABLENAME | | | | |
|* 2 | INDEX RANGE SCAN| WHATEVER_INDEX_IDX | 49 | 2291 | 3 (0)| 00:00:01 |
—————————————————————————————————-Predicate Information (identified by operation id):
—————————————————2 – access(“ORDER_ID”=34438309)
Statistics
———————————————————–
3 user calls
0 physical read total multi block requests
3914500 physical read total bytes
3827200 cell physical IO interconnect bytes
0 commit cleanout failures: block lost
0 IMU commits
1 IMU Flushes
0 IMU contention
0 IMU bind flushes
0 IMU mbu flush
So, from the above you can deduce the following:
- Are indexes being used
- Are there lot of Physical Reads
Table/Index Fragmentation
If there are frequent inserts/deletes on large tables, it is possible that Table and Index data has got fragmented, this can result in Slow Queries (often Delete Queries are slow because of this).
De-frag Table:
alter table TABLE_NAME move
Rebuild Index:
alter index INDEX_NAME rebuild;
If you de-frag table, always remember, you must rebuild ALL indexes on that table.
Re-Compute Statistics
TODO: More Info on this…
Analyze Table <TABLE_NAME> Compute Statistics;
How to authenticate against LDAP / Active Directory?
Problem Statement
Given a User Name and Password, you want to authenticate the same against LDAP or Active Directory (AD).
Solution – Using a Java Program
Here’s a simple example:
import java.util.*;
import javax.naming.*;
import javax.naming.directory.*;
public class Main {
public static void main(String[] args) {
try {
Hashtable env = new Hashtable();
env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory");
//NOTE: Replace with appropriate ldap hostname below
env.put(Context.PROVIDER_URL, "LDAP://ldaphost:389");
//NOTE: Usually DIGEST-MD5 usually works with Windows Active Directory. If not try 'Simple'
env.put(Context.SECURITY_AUTHENTICATION, "DIGEST-MD5");
//NOTE: Replace with appropriate username and passwd in next two lines.
env.put(Context.SECURITY_PRINCIPAL, "putUsernameHere");
env.put(Context.SECURITY_CREDENTIALS, "putPasswordHere>");
DirContext ctx = new InitialDirContext(env);
ctx.close();
}
catch(NamingException ne) {
System.out.println("Error authenticating user:");
System.out.println(ne.getMessage());
return;
}
System.out.println("OK, successfully authenticated user");
}
How to take a Java Heap Dump and analyze it?
To take a Heap Dump from Command Line:
First get the Java Applications Process Id, one way to do this is with: jps
jmap -dump:format=b,file=dump.bin <javaProcessIdHere>
The size of the heap dump file will be same as the heap memory in use at the time the command is run. For large heap sizes this can take several minutes to run, and can stall (make it unresponsive) the application during this time.
To get a summary of Object Instances and Sizes you can use this command:
jmap -histo:live <javaProcessIdHere>
Generally, this command will run quickly, and should be used when taking a heap dump will be too costly in terms of time-taken/size etc.
To get Heap Dump on Out of Memory Exception (available from Java 1.5.0_07 onwards):
Add the following param: -XX:+HeapDumpOnOutOfMemoryError
If you want the dump to go in a particular path then add: -XX:+HeapDumpOnOutOfMemoryError XX:HeapDumpPath=/usr/local/dumps
To initiate Heap Dump from within the Application Code:
We can also use jmap from our code. To get a pid from code use we need to use java.lang.management.ManagementFactory.
String name = ManagementFactory.getRuntimeMXBean().getName();
String pid = name.substring(0, name.indexOf("@"));
After that we can start jmap process like this:
String[] cmd = { "jmap", "-dump:file=/usr/local/heapdumps/dump.bin", pid };
Process p = Runtime.getRuntime().exec(cmd);
A simple Shell Script to Take Heap Dump every 30 seconds:
while true
do
jmap -dump:file=/tmp/java-`date +%s`.hprof <processIdOfJVM>
sleep 30
done
Heap Dump Analysis Tools
- Eclipse Memory Analyzer
- Java Visual VM (part of JDK)
- jhat – Java Heap Analysis Tool (Suitable for analyzing very big heap files)
How to diagnose Performance problems in Java Web Applications?
Problem Statement
Your Java/J2EE Application is performing sub-optimally.
Symptoms
- Slow (Web Page) Response Times, always or sometimes.
- High Memory Usage / Out-Of-Memory Errors
- Application stalls (stops responding)
- High CPU Utilization
Analysis
Step 1: Analyze Key Performance Parameters
- Enable JMX on the Application Server. Here is how you can do this.
- Now, use a tool like Java Visual VM, to view these Performance Parameters: CPU, Memory, Thread Usage
- This should tell you: if any of these resources(CPU/Memory/Threads) are heavily used
- Look for CPU Utilization graph” for any unusually high Garbage Collection.
Step 2: Analyze Thread Stack Dump
- Here is how you do this.
- This should tell you what your threads were doing when Thread Stack Dump was taken.
- You may want to take Thread Stack Dump multiple times to look for potential problems.
- If a very large number of Threads are in BLOCKED state, it is a sure sign of problem, the stack trace tells you what the Thread is blocked on. For example if there is a problem with Logging, it is seen that over a period of time All Threads get Blocked on Logging activity, and in therefore stalling the application.
Step 3: Analyze Heap Memory
- Take a Heap Dump( say by using jmap) and Analyze it (in tools like jhat). Here is how you do this.
- This should tell you what is using up your memory.
- Things to look for: Instance Counts (of Classes), Size of all Instances (of a Class).
Step 4: Analyze Business Transactions
- TODO: Here is how you do this.
Recent Comments