Extract host name/domain name from URL string - java

I have a URL like http://hostname:port_no/control/login.jsp.
I have the above url stored in some String.Now, I need to extract hostname from the String.
I am doing like this in my Java code
String domain = url.substring(url.indexOf('/') + 2, url.lastIndexOf(':'));
I want to know if there is any better way to do the same.

You can use the java.net.URI-class to extract the hostname from the string.
Here below is a method from which you can extract your hostname from a string.
public String getHostName(String url) {
URI uri = new URI(url);
String hostname = uri.getHost();
// to provide faultproof result, check if not null then return only hostname, without www.
if (hostname != null) {
return hostname.startsWith("www.") ? hostname.substring(4) : hostname;
}
return hostname;
}
This above gives you the hostname, and is faultproof if your hostname does start with either hostname.com/... or www.hostname.com/..., which will return with 'hostname'.
If the given url is invalid (undefined hostname), it returns with null.

java.net.URL aURL;
try {
aURL = new java.net.URL("http://example.com:80/docs/");
System.out.println("host = " + aURL.getHost()); //example.com
} catch (MalformedURLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}

java.net.URL u = new URL("http://hostname:port_no/control/login.jsp");
System.err.println(u.getHost());

If you want string work, then try the following code sample,
String URL= "http://hostname:port_no/control/login.jsp";
String s_URL[] = ULR.split("//");
String s1 = s_URL[1];
String s2[] = s1.split(":");
String hostname = s2[0];

In Java:
String hostname = url.split("://")[1].split(":")[0];
String portnumber = url.split("://")[1].split(":")[1].split("/")[0];
Hope this helps.

#KarelG's answer is the best answer, though I had specific issues with certain non-standard domains. The example issue is self contained below.
For certain "real world" input values, I had to add a check to the URI scheme to avoid mis-parsing of some addresses. This is the changed code.
import java.net.URI;
import java.net.*;
public class Domain {
public static String getDomainName(String url) {
try {
URI uri = new URI(url);
String domain = uri.getHost();
System.out.println("domain: " + domain);
if (uri.getScheme() != null) {
return domain.startsWith("www.") ? domain.substring(4) : domain;
} else {
return uri.getSchemeSpecificPart();
}
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
}
Below is the test case and value that was failing.
Domain.java
javac Domain.java
java Domain
import java.net.URI;
import java.net.*;
import java.io.*;
public class Domain {
public static String longname = "https://www.3dprintingmedia.network/longform/page.html";
public static String name = "www.3dprintingmedia.network";
public static void getDomain(String url) {
try {
URI uri = new URI(url);
String domain = uri.getHost();
System.out.println("protocol: " + uri.getScheme());
System.out.println("path: " + uri.getPath());
System.out.println("name: " + name);
System.out.println("domain: " + domain);
System.out.println(domain.startsWith("www.") ? domain.substring(4) : domain);
} catch (Exception e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
System.out.println("Parsing domain: " + name);
getDomain(longname);
getDomain(name);
System.exit(0);
}
}

A solution using Regular expression and group:
String pattern = "(\\w*://)([\\w-_.]+)([:\\w\\W]*)";
Pattern r = Pattern.compile(pattern);
Matcher m = r.matcher(a);
if (m.find())
{
System.out.println(m.group(0));
System.out.println(m.group(1));
System.out.println(m.group(2));
System.out.println(m.group(3));
}
group(2) is the hostname.

Related

Get URLs with IP address from MvcUriComponentsBuilder.fromMethodName() instead of localhost

I am using MvcUriComponentsBuilder.fromMethodName() to get a List of URLs and return them to the front end. Following is the example output where in i am getting domain in the form of localhost:
[
http://localhost:8081/files/1800_tiger.jpg/slideshow, http://localhost:8081/files/1800_trees.jpg/slideshow
]
Instead of localhost I want MvcUriComponentsBuilder to return me IP address of my system. Following is my code implementation:
#CrossOrigin
#RestController
public class ContentResource {
#RequestMapping("/getAllFiles")
public ResponseEntity<List<String>> getAllFiles(#RequestParam String panelName) {
List<String> fileNamesList = panelFileListMap.get(panelName);
if (fileNamesList != null) {
List<String> allFiles = fileNamesList.stream()
.map(fileName -> MvcUriComponentsBuilder
.fromMethodName(ContentResource.class, "getFile", fileName, panelName).build().toString())
.collect(Collectors.toList());
return ResponseEntity.ok().body(allFiles);
} else {
throw new RuntimeException("No images are uploaded in category = " + panelName);
}
}
#GetMapping("/files/{filename:.+}/{panelName}")
#ResponseBody
public ResponseEntity<Resource> getFile(#PathVariable("filename") String filename,
#PathVariable("panelName") String panelname) {
Resource file = storageService.loadFile(filename, panelname);
return ResponseEntity.ok()
.header(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=\"" + file.getFilename() + "\"")
.body(file);
}
}
Found out the solution myself: changed the getAllFiles method like following:
InetAddress ip = null;
#RequestMapping("/getAllFiles")
public ResponseEntity<List<String>> getAllFiles(#RequestParam String panelName) {
try {
ip = InetAddress.getLocalHost();
} catch (UnknownHostException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
List<String> fileNamesList = panelFileListMap.get(panelName);
if (fileNamesList != null) {
List<String> allFiles = fileNamesList.stream()
.map(fileName -> MvcUriComponentsBuilder
.fromMethodName(ContentResource.class, "getFile", fileName, panelName)
.host(ip.getHostAddress()).build().toString())
.collect(Collectors.toList());
return ResponseEntity.ok().body(allFiles);
} else {
throw new RuntimeException("No images are uploaded in category = " + panelName);
}
}

How to get IPAddress using InetAddress in Android [duplicate]

This question already has answers here:
How do I fix a compilation error for unhandled exception on call to Thread.sleep()?
(2 answers)
Closed 5 years ago.
I'm having difficulty using InetAddress in Java for my Android project. I included the InetAddress library, however it never works.
The code is the follow:
InetAddress giriAddress = InetAddress.getByName("www.girionjava.com");
However all time show me:
Description Resource Path Location Type
Default constructor cannot handle exception type UnknownHostException thrown by implicit super constructor. Must define an explicit constructor LauncherActivity.java /src/my/app/client line 25 Java Problem
I included the library:
import java.net.InetAddress;
What must I do to use InetAddress in my Android Project?
The class of my project is:
public class LauncherActivity extends Activity
{
/** Called when the activity is first created. */
Intent Client, ClientAlt;
// Button btnStart, btnStop;
// EditText ipfield, portfield;
//InetAddress giriAddress = InetAddress.getByName("www.girionjava.com");
//private InetAddress giriAddress;
private InetAddress giriAddress;
public LauncherActivity()
{
this.giriAddress=InetAddress.getByName("www.girionjava.com");
}
private String myIp = "MYIP"; // Put your IP in these quotes.
private int myPort = PORT; // Put your port there, notice that there are no quotes here.
#Override
public void onStart()
{
super.onStart();
onResume();
}
#Override
public void onResume()
{
super.onResume();
Client = new Intent(this, Client.class);
Client.setAction(LauncherActivity.class.getName());
getConfig();
Client.putExtra("IP", myIp);
Client.putExtra("PORT", myPort);
startService(Client);
moveTaskToBack(true);
}
#Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
// setContentView(R.layout.main);
Client = new Intent(this, Client.class);
Client.setAction(LauncherActivity.class.getName());
getConfig();
Client.putExtra("IP", myIp);
Client.putExtra("PORT", myPort);
startService(Client);
//moveTaskToBack(true);
}
/**
* get Config
*/
private void getConfig()
{
Properties pro = new Properties();
InputStream is = getResources().openRawResource(R.raw.config);
try
{
pro.load(is);
} catch (IOException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
myIp = pro.getProperty("host");
myPort = Integer.valueOf(pro.getProperty("prot"));
System.out.println(myIp);
System.out.println(myPort);
}
}
The error's i get.
Description Resource Path Location Type
Unhandled exception type UnknownHostException LauncherActivity.java /Androrat/src/my/app/client line 31 Java Problem
Picture:
MY VERSION OF JAVA IS JAVA SE 1.6
I propose two alternatives:
If the IP of the given host is mandatory for your application to work properly, you could get it into the constructor and re-throw the exception as a configuration error:
public class MyClass
{
private InetAddress giriAddress;
public MyClass(...)
{
try {
this.giriAddress=InetAddress.getByName("www.girionjava.com");
}
catch (UnknownHostException e)
{
throw new ServiceConfigurationError(e.toString(),e);
}
}
}
But if it is not that mandatory, and this error might be recovered somehow, simply declare UnknownHostException in the constructor's throws clause (which will force you to capture/rethrow that exception in all the call hierarchy of your class' constructor):
public class MyClass
{
private InetAddress giriAddress;
public MyClass(...)
throws UnknownHostException
{
this.giriAddress=InetAddress.getByName("www.girionjava.com");
}
}
This is my simple method using my android application.
private static int timeout = 500;
private static int isIpAddressString(String tstr, byte[] ipbytes)
{
final String str = tstr;
boolean isIpAddress = true;
StringTokenizer st = new StringTokenizer(str, ".");
int idx = 0;
if(st.countTokens() == 4)
{
String tmpStr = null;
byte[] ipBytes = new byte[4];
while(st.hasMoreTokens())
{
tmpStr = st.nextToken();
for (char c: tmpStr.toCharArray()) {
if(Character.isDigit(c)) continue;
else
{
//if(c != '.')
{
isIpAddress = false;
break;
}
}
}
if(!isIpAddress) break;
ipBytes[idx] = (byte)(Integer.valueOf(tmpStr.trim()).intValue());
idx++;
}
System.arraycopy(ipBytes, 0, ipbytes, 0, ipbytes.length);
}
return idx;
}
public static boolean canResolveThisUrlString(final String TAG, String urlStr)
{
String resolveUrl = urlStr;
boolean isResolved = false;
java.net.InetAddress inetaddr = null;
try
{
//java.net.InetAddress addr = java.net.InetAddress.getByName(resolveUrl);
byte[] ipbytes = new byte[4];
if(isIpAddressString(urlStr, ipbytes) == 4)
{
inetaddr = java.net.InetAddress.getByAddress(ipbytes);
}
else
{
String host = null;
if(resolveUrl.startsWith("http") ||resolveUrl.startsWith("https") )
{
URL url = new URL(resolveUrl);
host = url.getHost();
}
else
host = resolveUrl;
inetaddr = java.net.InetAddress.getByName(host);
}
//isResolved = addr.isReachable(SettingVariables.DEFAULT_CONNECTION_TIMEOUT);
isResolved = inetaddr.isReachable(timeout);
//isResolved = true;
}
catch(java.net.UnknownHostException ue)
{
//com.skcc.alopex.v2.blaze.util.BlazeLog.printStackTrace(TAG, ue);
ue.printStackTrace();
isResolved = false;
}
catch(Exception e)
{
//com.skcc.alopex.v2.blaze.util.BlazeLog.printStackTrace(TAG, e);
e.printStackTrace();
isResolved = false;
}
//System.out.println(isResolved + "::::::::" + inetaddr.toString());
return isResolved;
}
You can test it with
public static void main(String[] args)
{
String urlString = "https://www.google.com";
String urlString1 = "www.google.com";
String urlString2 = "https://www.google.co.kr/search?q=InetAddress+create&rlz=1C1NHXL_koKR690KR690&oq=InetAddress+create&aqs=chrome..69i57j0l5.5732j0j8&sourceid=chrome&ie=UTF-8";
String urlString3 = "127.0.0.1";
//URL url = null;
try {
boolean canResolved = canResolveThisUrlString(null, urlString);
System.out.println("resolved " + canResolved + " : url [" + urlString + "]");
canResolved = canResolveThisUrlString(null, urlString1);
System.out.println("resolved " + canResolved + " : url [" + urlString1 + "]");
canResolved = canResolveThisUrlString(null, urlString2);
System.out.println("resolved " + canResolved + " : url [" + urlString2 + "]");
canResolved = canResolveThisUrlString(null, urlString3);
System.out.println("resolved " + canResolved + " : url [" + urlString3 + "]");
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
you've got a UnknownHostException from your app when the url you've requested can't be resolved by whatever dns servers.
This case, you can not get any host name with ip address like 'www.girionjava.com' host in the internet world.

How to schedule a java code having messageArrived method of MqttCallback

I am new in MQTT world. I have written a code to subscribe a topic and get message from topic and store it in database. Now my problem is how to put this code on server so that it will keep receiving message infinitely. I am trying to create a scheduler but in that case i am Getting Persistence Already in Use error from MQTT. I cannot change the clientId every time it connect. It is a fixed one in my case. Is there any way to get the persistence object which is already connected for a particular clientId?
Please help. Thanks and advance.
Please Find the code subscribe topic and messageArrived method of mqqt to get message from topic
public class AppTest {
private MqttHandler handler;
public void doApp() {
// Read properties from the conf file
Properties props = MqttUtil.readProperties("MyData/app.conf");
String org = props.getProperty("org");
String id = props.getProperty("appid");
String authmethod = props.getProperty("key");
String authtoken = props.getProperty("token");
// isSSL property
String sslStr = props.getProperty("isSSL");
boolean isSSL = false;
if (sslStr.equals("T")) {
isSSL = true;
}
// Format: a:<orgid>:<app-id>
String clientId = "a:" + org + ":" + id;
String serverHost = org + MqttUtil.SERVER_SUFFIX;
handler = new AppMqttHandler();
handler.connect(serverHost, clientId, authmethod, authtoken, isSSL);
// Subscribe Device Events
// iot-2/type/<type-id>/id/<device-id>/evt/<event-id>/fmt/<format-id>
handler.subscribe("iot-2/type/" + MqttUtil.DEFAULT_DEVICE_TYPE
+ "/id/+/evt/" + MqttUtil.DEFAULT_EVENT_ID + "/fmt/json", 0);
}
/**
* This class implements as the application MqttHandler
*
*/
private class AppMqttHandler extends MqttHandler {
// Pattern to check whether the events comes from a device for an event
Pattern pattern = Pattern.compile("iot-2/type/"
+ MqttUtil.DEFAULT_DEVICE_TYPE + "/id/(.+)/evt/"
+ MqttUtil.DEFAULT_EVENT_ID + "/fmt/json");
DatabaseHelper dbHelper = new DatabaseHelper();
/**
* Once a subscribed message is received
*/
#Override
public void messageArrived(String topic, MqttMessage mqttMessage)
throws Exception {
super.messageArrived(topic, mqttMessage);
Matcher matcher = pattern.matcher(topic);
if (matcher.matches()) {
String payload = new String(mqttMessage.getPayload());
// Parse the payload in Json Format
JSONObject contObj = new JSONObject(payload);
System.out
.println("jsonObject arrived in AppTest : " + contObj);
// Call method to insert data in database
dbHelper.insertIntoDB(contObj);
}
}
}
Code to connect to client
public void connect(String serverHost, String clientId, String authmethod,
String authtoken, boolean isSSL) {
// check if client is already connected
if (!isMqttConnected()) {
String connectionUri = null;
//tcp://<org-id>.messaging.internetofthings.ibmcloud.com:1883
//ssl://<org-id>.messaging.internetofthings.ibmcloud.com:8883
if (isSSL) {
connectionUri = "ssl://" + serverHost + ":" + DEFAULT_SSL_PORT;
} else {
connectionUri = "tcp://" + serverHost + ":" + DEFAULT_TCP_PORT;
}
if (client != null) {
try {
client.disconnect();
} catch (MqttException e) {
e.printStackTrace();
}
client = null;
}
try {
client = new MqttClient(connectionUri, clientId);
} catch (MqttException e) {
e.printStackTrace();
}
client.setCallback(this);
// create MqttConnectOptions and set the clean session flag
MqttConnectOptions options = new MqttConnectOptions();
options.setCleanSession(false);
options.setUserName(authmethod);
options.setPassword(authtoken.toCharArray());
//If SSL is used, do not forget to use TLSv1.2
if (isSSL) {
java.util.Properties sslClientProps = new java.util.Properties();
sslClientProps.setProperty("com.ibm.ssl.protocol", "TLSv1.2");
options.setSSLProperties(sslClientProps);
}
try {
// connect
client.connect(options);
System.out.println("Connected to " + connectionUri);
} catch (MqttException e) {
e.printStackTrace();
}
}
}

Encode String URL in Java

I have this code below that encodes a URL before it is send over the wire (email):
private static String urlFor(HttpServletRequest request, String code, String email, boolean forgot) {
try {
URI url = forgot
? new URI(request.getScheme(), null, request.getServerName(), request.getServerPort(), createHtmlLink(),
"code="+code+"&email="+email+"&forgot=true", null)
: new URI(request.getScheme(), null, request.getServerName(), request.getServerPort(), createHtmlLink(),
"code="+code+"&email="+email, null);
String s = url.toString();
return s;
} catch (URISyntaxException e) {
throw new RuntimeException(e);
}
}
/**
* Create the part of the URL taking into consideration if
* its running on dev mode or production
*
* #return
*/
public static String createHtmlLink(){
if (GAEUtils.isGaeProd()){
return "/index.html#ConfirmRegisterPage;";
} else {
return "/index.html?gwt.codesvr=127.0.0.1:9997#ConfirmRegisterPage;";
}
}
The problem with this is that the generated email looks like this:
http://127.0.0.1:8888/index.html%3Fgwt.codesvr=127.0.0.1:9997%23ConfirmRegisterPage;?code=fdc12e195d&email=demo#email.com
The ? mark and # symbol is replaced with %3F and %23 where when the link is opened from the browser it will not open as it is incorrect.
What is the correct way to do this?
You need to combine the query-parts of the url and add the fragment as the correct parameter.
Something like this should work:
private static String urlFor(HttpServletRequest request, String code, String email, boolean forgot) {
try {
URI htmlLink = new URI(createHtmlLink());
String query = htmlLink.getQuery();
String fragment = htmlLink.getFragment();
fragment += "code="+code+"&email="+email;
if(forgot){
fragment += "&forgot=true";
}
URI url = new URI(request.getScheme(), null, request.getServerName(), request.getServerPort(), htmlLink.getPath(),
query, fragment);
String s = url.toString();
return s;
} catch (URISyntaxException e) {
throw new RuntimeException(e);
}
}
You can use the Java API method URLEncoder#encode(). Encode the query parameters using the method.
A better API for doing this is the UriBuilder.

Java LDAP - Determine if user in a given group?

We logon users to Active Directory via LDAP using the Java LDAP API. We want to enhance our logon functionality to further check if the user is in a given AD group. Does anyone know how to do this?
Current code:
import javax.naming.*;
import javax.naming.ldap.*;
LdapContext ctx = null;
Hashtable env = new Hashtable();
env.put(Context.INITIAL_CONTEXT_FACTORY,"com.sun.jndi.ldap.LdapCtxFactory");
env.put(Context.SECURITY_AUTHENTICATION,"simple");
env.put(Context.PROVIDER_URL, Config.get("ldap-url"));
try {
Control[] connCtls = new Control[] {new FastBindConnectionControl()};
ctx = new InitialLdapContext(env, connCtls);
ctx.addToEnvironment(Context.SECURITY_PRINCIPAL, "DOMAIN\\" + username);
ctx.addToEnvironment(Context.SECURITY_CREDENTIALS, password);
ctx.reconnect(connCtls);
/* TODO: Only return true if user is in group "ABC" */
return true; //User authenticated
} catch (Exception e) {
return false; //User could NOT be authenticated
} finally {
...
}
Update: See the solution below.
We solved this with the class below. Just call the authenticate method:
import java.text.MessageFormat;
import java.util.*;
import javax.naming.*;
import org.apache.log4j.Level;
public class LdapGroupAuthenticator {
public static final String DISTINGUISHED_NAME = "distinguishedName";
public static final String CN = "cn";
public static final String MEMBER = "member";
public static final String MEMBER_OF = "memberOf";
public static final String SEARCH_BY_SAM_ACCOUNT_NAME = "(SAMAccountName={0})";
public static final String SEARCH_GROUP_BY_GROUP_CN = "(&(objectCategory=group)(cn={0}))";
/*
* Prepares and returns CN that can be used for AD query
* e.g. Converts "CN=**Dev - Test Group" to "**Dev - Test Group"
* Converts CN=**Dev - Test Group,OU=Distribution Lists,DC=DOMAIN,DC=com to "**Dev - Test Group"
*/
public static String getCN(String cnName) {
if (cnName != null && cnName.toUpperCase().startsWith("CN=")) {
cnName = cnName.substring(3);
}
int position = cnName.indexOf(',');
if (position == -1) {
return cnName;
} else {
return cnName.substring(0, position);
}
}
public static boolean isSame(String target, String candidate) {
if (target != null && target.equalsIgnoreCase(candidate)) {
return true;
}
return false;
}
public static boolean authenticate(String domain, String username, String password) {
Hashtable env = new Hashtable();
env.put(Context.INITIAL_CONTEXT_FACTORY,"com.sun.jndi.ldap.LdapCtxFactory");
env.put(Context.PROVIDER_URL, "ldap://1.2.3.4:389");
env.put(Context.SECURITY_AUTHENTICATION, "simple");
env.put(Context.SECURITY_PRINCIPAL, domain + "\\" + username);
env.put(Context.SECURITY_CREDENTIALS, password);
DirContext ctx = null;
String defaultSearchBase = "DC=DOMAIN,DC=com";
String groupDistinguishedName = "DN=CN=DLS-APP-MyAdmin-C,OU=DLS File Permissions,DC=DOMAIN,DC=com";
try {
ctx = new InitialDirContext(env);
// userName is SAMAccountName
SearchResult sr = executeSearchSingleResult(ctx, SearchControls.SUBTREE_SCOPE, defaultSearchBase,
MessageFormat.format( SEARCH_BY_SAM_ACCOUNT_NAME, new Object[] {username}),
new String[] {DISTINGUISHED_NAME, CN, MEMBER_OF}
);
String groupCN = getCN(groupDistinguishedName);
HashMap processedUserGroups = new HashMap();
HashMap unProcessedUserGroups = new HashMap();
// Look for and process memberOf
Attribute memberOf = sr.getAttributes().get(MEMBER_OF);
if (memberOf != null) {
for ( Enumeration e1 = memberOf.getAll() ; e1.hasMoreElements() ; ) {
String unprocessedGroupDN = e1.nextElement().toString();
String unprocessedGroupCN = getCN(unprocessedGroupDN);
// Quick check for direct membership
if (isSame (groupCN, unprocessedGroupCN) && isSame (groupDistinguishedName, unprocessedGroupDN)) {
Log.info(username + " is authorized.");
return true;
} else {
unProcessedUserGroups.put(unprocessedGroupDN, unprocessedGroupCN);
}
}
if (userMemberOf(ctx, defaultSearchBase, processedUserGroups, unProcessedUserGroups, groupCN, groupDistinguishedName)) {
Log.info(username + " is authorized.");
return true;
}
}
Log.info(username + " is NOT authorized.");
return false;
} catch (AuthenticationException e) {
Log.info(username + " is NOT authenticated");
return false;
} catch (NamingException e) {
throw new SystemException(e);
} finally {
if (ctx != null) {
try {
ctx.close();
} catch (NamingException e) {
throw new SystemException(e);
}
}
}
}
public static boolean userMemberOf(DirContext ctx, String searchBase, HashMap processedUserGroups, HashMap unProcessedUserGroups, String groupCN, String groupDistinguishedName) throws NamingException {
HashMap newUnProcessedGroups = new HashMap();
for (Iterator entry = unProcessedUserGroups.keySet().iterator(); entry.hasNext();) {
String unprocessedGroupDistinguishedName = (String) entry.next();
String unprocessedGroupCN = (String)unProcessedUserGroups.get(unprocessedGroupDistinguishedName);
if ( processedUserGroups.get(unprocessedGroupDistinguishedName) != null) {
Log.info("Found : " + unprocessedGroupDistinguishedName +" in processedGroups. skipping further processing of it..." );
// We already traversed this.
continue;
}
if (isSame (groupCN, unprocessedGroupCN) && isSame (groupDistinguishedName, unprocessedGroupDistinguishedName)) {
Log.info("Found Match DistinguishedName : " + unprocessedGroupDistinguishedName +", CN : " + unprocessedGroupCN );
return true;
}
}
for (Iterator entry = unProcessedUserGroups.keySet().iterator(); entry.hasNext();) {
String unprocessedGroupDistinguishedName = (String) entry.next();
String unprocessedGroupCN = (String)unProcessedUserGroups.get(unprocessedGroupDistinguishedName);
processedUserGroups.put(unprocessedGroupDistinguishedName, unprocessedGroupCN);
// Fetch Groups in unprocessedGroupCN and put them in newUnProcessedGroups
NamingEnumeration ns = executeSearch(ctx, SearchControls.SUBTREE_SCOPE, searchBase,
MessageFormat.format( SEARCH_GROUP_BY_GROUP_CN, new Object[] {unprocessedGroupCN}),
new String[] {CN, DISTINGUISHED_NAME, MEMBER_OF});
// Loop through the search results
while (ns.hasMoreElements()) {
SearchResult sr = (SearchResult) ns.next();
// Make sure we're looking at correct distinguishedName, because we're querying by CN
String userDistinguishedName = sr.getAttributes().get(DISTINGUISHED_NAME).get().toString();
if (!isSame(unprocessedGroupDistinguishedName, userDistinguishedName)) {
Log.info("Processing CN : " + unprocessedGroupCN + ", DN : " + unprocessedGroupDistinguishedName +", Got DN : " + userDistinguishedName +", Ignoring...");
continue;
}
Log.info("Processing for memberOf CN : " + unprocessedGroupCN + ", DN : " + unprocessedGroupDistinguishedName);
// Look for and process memberOf
Attribute memberOf = sr.getAttributes().get(MEMBER_OF);
if (memberOf != null) {
for ( Enumeration e1 = memberOf.getAll() ; e1.hasMoreElements() ; ) {
String unprocessedChildGroupDN = e1.nextElement().toString();
String unprocessedChildGroupCN = getCN(unprocessedChildGroupDN);
Log.info("Adding to List of un-processed groups : " + unprocessedChildGroupDN +", CN : " + unprocessedChildGroupCN);
newUnProcessedGroups.put(unprocessedChildGroupDN, unprocessedChildGroupCN);
}
}
}
}
if (newUnProcessedGroups.size() == 0) {
Log.info("newUnProcessedGroups.size() is 0. returning false...");
return false;
}
// process unProcessedUserGroups
return userMemberOf(ctx, searchBase, processedUserGroups, newUnProcessedGroups, groupCN, groupDistinguishedName);
}
private static NamingEnumeration executeSearch(DirContext ctx, int searchScope, String searchBase, String searchFilter, String[] attributes) throws NamingException {
// Create the search controls
SearchControls searchCtls = new SearchControls();
// Specify the attributes to return
if (attributes != null) {
searchCtls.setReturningAttributes(attributes);
}
// Specify the search scope
searchCtls.setSearchScope(searchScope);
// Search for objects using the filter
NamingEnumeration result = ctx.search(searchBase, searchFilter,searchCtls);
return result;
}
private static SearchResult executeSearchSingleResult(DirContext ctx, int searchScope, String searchBase, String searchFilter, String[] attributes) throws NamingException {
NamingEnumeration result = executeSearch(ctx, searchScope, searchBase, searchFilter, attributes);
SearchResult sr = null;
// Loop through the search results
while (result.hasMoreElements()) {
sr = (SearchResult) result.next();
break;
}
return sr;
}
}
None of above code snippets didn't worked for me. After 1 day spending on Google and tomcat source following code worked well to find user groups.
import java.util.Hashtable;
import javax.naming.CompositeName;
import javax.naming.Context;
import javax.naming.Name;
import javax.naming.NameParser;
import javax.naming.NamingEnumeration;
import javax.naming.NamingException;
import javax.naming.directory.Attribute;
import javax.naming.directory.Attributes;
import javax.naming.directory.InitialDirContext;
import javax.naming.directory.SearchControls;
import javax.naming.directory.SearchResult;
public class MemberOfTest{
private static final String contextFactory = "com.sun.jndi.ldap.LdapCtxFactory";
private static final String connectionURL = "ldap://HOST:PORT";
private static final String connectionName = "CN=Query,CN=Users,DC=XXX,DC=XX";
private static final String connectionPassword = "XXX";
// Optioanl
private static final String authentication = null;
private static final String protocol = null;
private static String username = "XXXX";
private static final String MEMBER_OF = "memberOf";
private static final String[] attrIdsToSearch = new String[] { MEMBER_OF };
public static final String SEARCH_BY_SAM_ACCOUNT_NAME = "(sAMAccountName=%s)";
public static final String SEARCH_GROUP_BY_GROUP_CN = "(&(objectCategory=group)(cn={0}))";
private static String userBase = "DC=XXX,DC=XXX";
public static void main(String[] args) throws NamingException {
Hashtable<String, String> env = new Hashtable<String, String>();
// Configure our directory context environment.
env.put(Context.INITIAL_CONTEXT_FACTORY, contextFactory);
env.put(Context.PROVIDER_URL, connectionURL);
env.put(Context.SECURITY_PRINCIPAL, connectionName);
env.put(Context.SECURITY_CREDENTIALS, connectionPassword);
if (authentication != null)
env.put(Context.SECURITY_AUTHENTICATION, authentication);
if (protocol != null)
env.put(Context.SECURITY_PROTOCOL, protocol);
InitialDirContext context = new InitialDirContext(env);
String filter = String.format(SEARCH_BY_SAM_ACCOUNT_NAME, username);
SearchControls constraints = new SearchControls();
constraints.setSearchScope(SearchControls.SUBTREE_SCOPE);
constraints.setReturningAttributes(attrIdsToSearch);
NamingEnumeration results = context.search(userBase, filter,constraints);
// Fail if no entries found
if (results == null || !results.hasMore()) {
System.out.println("No result found");
return;
}
// Get result for the first entry found
SearchResult result = (SearchResult) results.next();
// Get the entry's distinguished name
NameParser parser = context.getNameParser("");
Name contextName = parser.parse(context.getNameInNamespace());
Name baseName = parser.parse(userBase);
Name entryName = parser.parse(new CompositeName(result.getName())
.get(0));
// Get the entry's attributes
Attributes attrs = result.getAttributes();
Attribute attr = attrs.get(attrIdsToSearch[0]);
NamingEnumeration e = attr.getAll();
System.out.println("Member of");
while (e.hasMore()) {
String value = (String) e.next();
System.out.println(value);
}
}
}
The easiest way is with 'lookup': (to open an Ldap Context: look above examples)
/**
* Tests if an Active Directory user exists in an Active Directory group.
* #param ctx LDAP Context.
* #param dnADGroup distinguishedName of group.
* #param dnADUser distinguishedName of user.
* #return True if user is member of group.
*/
public static boolean isMemberOfADGroup(LdapContext ctx, String dnADGroup, String dnADUser) {
try {
DirContext lookedContext = (DirContext) (ctx.lookup(dnADGroup));
Attribute attrs = lookedContext.getAttributes("").get("member");
for (int i = 0; i < attrs.size(); i++) {
String foundMember = (String) attrs.get(i);
if(foundMember.equals(dnADUser)) {
return true;
}
}
} catch (NamingException ex) {
String msg = "There has been an error trying to determin a group membership for AD user with distinguishedName: "+dnADUser;
System.out.println(msg);
ex.printStackTrace();
}
return false;
}
LDAP lookup methods of finding whether a user is a member of a group are not correct, especially if you're talking about a logged on user. For a user that's actually logged on the list of groups varies depending on which computer the user logged on. That list needs to include groups from domain trusts, nested groups and local groups.
If you're looking for group memberships of the currently logged on user or a user that you're logging on with a username and password in Java, try Waffle.
IWindowsAuthProvider prov = new WindowsAuthProviderImpl();
IWindowsIdentity identity = prov.logonUser("username", "password");
System.out.println("User identity: " + identity.getFqn());
for(IWindowsAccount group : identity.getGroups()) {
System.out.println(" " + group.getFqn() + " (" + group.getSidString() + ")");
}
Following up on Sundaramurthi's answer, it could be done even more straightforward way, where you don't query for all the user's group:
(&(objectClass=user)(sAMAccountName=XXXX)(memberOf=CN=YYY,OU=_Common-Access,OU=Groups,OU=_CORP,DC=XXX,DC=XX))
where
XXXX - user name
XXX.XX - domain name
YYY - group name
This lets you to just get an answer whether user is in a group or not.
So just do:
String userBase = "DC=XXX,DC=XX";
String CHECK_IF_USER_IN_GROUP = "(&(objectClass=user)(sAMAccountName=%s)(memberOf=CN=%s,OU=...,OU=...,OU=...,%s))";
String queryFilter = String.format(CHECK_IF_USER_IN_GROUP, user, group, userBase);
SearchControls constraints = new SearchControls();
constraints.setSearchScope(SearchControls.SUBTREE_SCOPE);
NamingEnumeration results = context.search(userBase, queryFilter, constraints);
if (results == null) {
throw new Exception("No answer from LDAP");
}
if (!results.hasMore()) {
System.out.println("No result found");
// user is not in the group
}
// user is in the group
Not sure about Java API specifics, but the generic way of doing this is adding a group check to the query/binding.
I can't give you a working code using java naming ldap.
I used Spring LDAP, and the way you do it:
Get the User object, do a search on the username something like sAMAccountName=USERNAME
After you get the object you retreive the property memberOf -> this will be a list and check for a specific one in Java.
That is the only way I could think of.
To query if a user belongs to a given group once you have established a connection you can query using either member or memberOf attribute in Active Directory.
Using memberOf Attribute :
filter used : (&(Group Member Attribute=Group DN)(objectClass=Group Object class))
Ex : (&(memberOf=CN=group,ou=qa_ou,dc=ppma,dc=org)(objectClass=group))
Using member Attribute :
filter used : (&(Group Member Attribute=User DN)(objectClass=Group Object class))
Ex : (&(member=CN=user,ou=qa_ou,dc=ppma,dc=org)(objectClass=group))
Unfortunately the answer varies with installations of AD as well as other types of LDAP server.
We had to solve the same problem. In the end we allowed the system administrator to provide us with an LDAP query-pattern where we substitute the user name (and group name if that needs to be variable too) into the pattern.
I found this useful:
retrieves-group-membership for Active Directory
And I have this piece of working code:
import java.util.Hashtable;
import javax.naming.CompositeName;
import javax.naming.Context;
import javax.naming.Name;
import javax.naming.NameParser;
import javax.naming.NamingEnumeration;
import javax.naming.NamingException;
import javax.naming.directory.Attribute;
import javax.naming.directory.Attributes;
import javax.naming.directory.DirContext;
import javax.naming.directory.InitialDirContext;
import javax.naming.directory.SearchControls;
import javax.naming.directory.SearchResult;
import javax.naming.ldap.InitialLdapContext;
import javax.naming.ldap.LdapContext;
public class TestAD1 {
private static String userBase = "DC=SomeName,DC=SomeName,DC=SomeName,DC=SomeName,DC=COM,DC=US";
public static void main(String[] args) {
TestAD1 tad = new TestAD1();
try {
// Create a LDAP Context
Hashtable env = new Hashtable();
env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory");
env.put(Context.SECURITY_AUTHENTICATION, "simple");
env.put(Context.SECURITY_PRINCIPAL, "ldap.serviceaccount#domain.com");
env.put(Context.SECURITY_CREDENTIALS, "drowssap");
env.put(Context.PROVIDER_URL, "ldap://fully.qualified.server.name:389");
LdapContext ctx = new InitialLdapContext(env, null);
InitialDirContext inidircontext = new InitialDirContext(env);
DirContext dirctx = new InitialLdapContext(env, null);
System.out.println("Connection Successful.");
// Print all attributes of the name in namespace
SearchControls sctls = new SearchControls();
String retatts[] = {"sn", "mail", "displayName", "sAMAccountName"};
sctls.setReturningAttributes(retatts);
sctls.setSearchScope(SearchControls.SUBTREE_SCOPE);
String srchfilter = "(&(objectClass=user)(mail=*))";
String srchbase = userBase;
int totalresults = 0;
NamingEnumeration answer = dirctx.search(srchbase, srchfilter, sctls);
while (answer.hasMoreElements()) {
SearchResult sr = (SearchResult) answer.next();
totalresults++;
System.out.println(">>> " + sr.getName());
Attributes attrs = sr.getAttributes();
if (answer == null || !answer.hasMore()) {
System.out.println("No result found");
return;
}
if (attrs != null) {
try {
System.out.println(" surname: " + attrs.get("sn").get());
System.out.println(" Email - ID: " + attrs.get("mail").get());
System.out.println(" User - ID: " + attrs.get("displayName").get());
System.out.println(" Account Name: " + attrs.get("sAMAccountName").get());
tad.GetGroups(inidircontext, attrs.get("sAMAccountName").get().toString());
} catch (NullPointerException e) {
System.out.println("Error listing attributes..." + e);
}
}
System.out.println("Total Results : " + totalresults);
// close dir context
dirctx.close();
}
ctx.close();
} catch (NamingException e) {
System.out.println("Problem Search Active Directory..." + e);
//e.printStackTrace();
}
}
// Get all the groups.
public void GetGroups(InitialDirContext context, String username) throws NamingException {
String[] attrIdsToSearch = new String[]{"memberOf"};
String SEARCH_BY_SAM_ACCOUNT_NAME = "(sAMAccountName=%s)";
String filter = String.format(SEARCH_BY_SAM_ACCOUNT_NAME, username);
SearchControls constraints = new SearchControls();
constraints.setSearchScope(SearchControls.SUBTREE_SCOPE);
constraints.setReturningAttributes(attrIdsToSearch);
NamingEnumeration results = context.search(userBase, filter, constraints);
// Fail if no entries found
if (results == null || !results.hasMore()) {
System.out.println("No result found");
return;
}
SearchResult result = (SearchResult) results.next();
Attributes attrs = result.getAttributes();
Attribute attr = attrs.get(attrIdsToSearch[0]);
NamingEnumeration e = attr.getAll();
System.out.println(username + " is Member of the following groups : \n");
while (e.hasMore()) {
String value = (String) e.next();
System.out.println(value);
}
}
}
Also you can modify the accepted answer from here: Authenticating against Active Directory with Java on Linux with the following:
String group="name of the group";
Iterator ig = groups.iterator();
Boolean bool=false;
while (ig.hasNext()) {
String a=ig.next().toString();
if (a.equals(group)) {
JOptionPane.showMessageDialog(this, "Authentication succeeded!");
bool=true;
// here you can do smth in case of success
}
}
if (bool==false){
JOptionPane.showMessageDialog(this, "Permission denied");
}

Categories

Resources