spring-ldap NameNotFoundException no such object - spring-ldap

I was using spring-ldap while I got this exception:
服务器未知异常:[LDAP: error code 32 - No Such Object];
nested exception is javax.naming.NameNotFoundException:
[LDAP: error code 32 - No Such Object]; remaining name 'uid=lyh,ou=Users,dc=xinsight,dc=com'
1.my configuration
<bean id="ldapTemplate" class="org.springframework.ldap.core.LdapTemplate">
<constructor-arg ref="contextSource"/>
</bean>
<bean id="contextSource"
class="org.springframework.ldap.core.support.LdapContextSource">
<property name="url" value="ldap://168.2.8.77:389" />
<property name="base" value="dc=xinsight,dc=com" />
<property name="userDn" value="cn=Manager,dc=xinsight,dc=com" />
<property name="password" value="psw" />
<!--<property name="referral" value="follow"/>-->
</bean>
2.my code
public void create() {
User user = new User();
user.setFdUsername("lyhtest");
user.setFdTenantName("root");
user.setFdLdapPassword("ldappsw");
user.setFdUserid(Long.valueOf(10));
Name dn = buildDn(user);
ldapTemplate.bind(dn, null, buildAttributes(user));
}
/**
* 动态创建DN
* spring-ldap提供了:LdapNameBuilder,LdapUtils
*/
private Name buildDn(User user) {
return LdapNameBuilder.newInstance(BASE_DN)
.add("ou", "Users")
.build();
}
/**
* 配置属性
* #param user
* #return
*/
private Attributes buildAttributes(User user) {
Attributes attrs = new BasicAttributes();
BasicAttribute objectclass = new BasicAttribute("objectclass");
objectclass.add("top");
objectclass.add("posixAccount");
objectclass.add("inetOrgPerson");
attrs.put(objectclass);
attrs.put("userPassword", user.getFdLdapPassword());
attrs.put("cn",user.getFdUsername()+"#"+user.getFdTenantName());
attrs.put("sn",user.getFdUsername()+"#"+user.getFdTenantName());
attrs.put("displayName",user.getFdUsername()+"#"+user.getFdTenantName());
attrs.put("homeDirectory","/root");
attrs.put("uidNumber",user.getFdUserid().toString());
attrs.put("uid",user.getFdUsername());
attrs.put("gidNumber","0");
return attrs;
}
3.ldap admin
ldap admin
4.I also writed the query method, I can get the userinfo from ldap. So the connection is ok.
Thanks for your help!

I have solved this problem.
1.I checked the log file of ldap admin, and I saw the "dn":
ou=Users,dc=xinsight,dc=com,dc=xinsight,dc=com
2.before and after
return LdapNameBuilder.newInstance(Base_DN)
.add("ou", "Users")
.add("uid","lyh3")
.build();
return LdapNameBuilder.newInstance()
.add("ou", "Users")
.add("uid","lyh3")
.build();
And after I removed the param: Base_DN, I created a user successfully. Then I check the log file of ldap admin, it shows that:
dn: ou=Users,dc=xinsight,dc=com
Although I don't know why the value of dn has duplicate 'dc=xinsight,dc=com'. I copied from the official document spring-ldap official doc, and it shows that a 'base_dn' is needed when building 'dn':
protected Name buildDn(Person p) {
return LdapNameBuilder.newInstance(BASE_DN)
.add("c", p.getCountry())
.add("ou", p.getCompany())
.add("cn", p.getFullname())
.build();
}

Related

Aggregator is failing after upgrading to Spring-Integration 4

We are using Spring-Integration in our project. We are trying to migrate from spring-integration-core:jar:3.0.1.RELEASE to spring-integration-core:jar:4.3.2.RELEASE, java 8, spring 4. We are running into issues with aggregator. Weirdly, the aggregator's method is not called during the execution. The configuration is shown below:
<!-- Store the original payload in header for future purpose -->
<int:header-enricher default-overwrite="true" should-skip-nulls="true" >
<int:header name="${headerNames.originalPayload}" expression="payload" />
</int:header-enricher>
<!-- split the issues-->
<int-xml:xpath-splitter >
<int-xml:xpath-expression expression="//transaction"/>
</int-xml:xpath-splitter>
<int:service-activator ref="httpOutboundGatewayHandler" method="buildHttpOutboundGatewayRequest" />
<int:header-filter header-names="accept-encoding"/>
<int-http:outbound-gateway url-expression="headers.restResourceUrl"
http-method-expression="headers.httpMethod"
extract-request-payload="true"
expected-response-type="java.lang.String">
</int-http:outbound-gateway>
<int:service-activator ref="msgHandler" method="buildMessageFromExtSysResponse" />
<int-xml:xslt-transformer xsl-resource="${stylesheet.PQGetWorklist-Response-MoveSources}" />
</int:chain>
<int:aggregator input-channel="PQGetWorklist-Aggregate-sources" output-channel="PQGetWorklist-MoveSourcesUnderIssues"
ref="xmlAggregator" method="aggregateSources">
</int:aggregator>
In the above code, <int-http:outbound-gateway is getting executed, but the XmlAggregator.aggregateSources is not called for unknown reasons. I could see that the message is sent to on the channel PQGetWorklist-Aggregate-sources. But from there the aggregator's method aggregateSources is not called. As a result, we are getting No reply received within timeout. Remember the same configuration is working fine with spring-integration-core:jar:3.0.1.RELEASE. The problem is seen only when we upgrade it to spring-integration-core:jar:4.3.2.RELEASE .
Here is my XmlAggregator.java
public class XmlAggregator {
private static final Logger logger = Logger.getLogger(XmlAggregator.class);
public Message aggregateSources(List < Message > messages) throws DocumentException {
Document mainDom = XmlParserUtil.convertString2Document("<Results> </Results>");
Document splitMessageDom = XmlParserUtil.convertString2Document(messages.get(0).getPayload().toString());
Document IssuesDom = XmlParserUtil.convertString2Document("<Issues> </Issues>");
Document sourcesDom = XmlParserUtil.convertString2Document("<RetrievedSources> </RetrievedSources>");
if(messages.get(0).getHeaders().get("jobDesignerJobName").equals("PQIssueInquiry")){
//extract callerType node
Element callerType = XmlParserUtil.getXmlElements(XmlParserUtil.convertString2Document(messages.get(0).getPayload().toString()), "//callerType").get(0);
//add callerType to root node
mainDom.getRootElement().content().add(callerType);
}
//extract sort node
Element sort = XmlParserUtil.getXmlElements(XmlParserUtil.convertString2Document(messages.get(0).getPayload().toString()), "//sort").get(0);
//add sort to root node
mainDom.getRootElement().content().add(sort);
//get all the issues
List < Element > transactionElements = XmlParserUtil.getXmlElements(splitMessageDom, "//transaction");
for (Element issue: transactionElements) {
// add all the issues to the IssuesDom
IssuesDom.getRootElement().content().add(issue);
}
//add all the issues to the root node
XmlParserUtil.appendChild(mainDom, IssuesDom, null);
for (Message source: messages) {
Document sourcesTempDom = XmlParserUtil.convertString2Document(source.getPayload().toString());
Reader xml = new StringReader((String) source.getPayload());
SAXReader reader = new SAXReader();
Document document = reader.read(xml);
//get all the sources
List < Element > sourceElements = XmlParserUtil.getXmlElements(sourcesTempDom, "//sources");
for (Element sources: sourceElements) {
//add all the sources to sourcesDom
sourcesDom.getRootElement().content().add(sources);
}
}
// add all the sources to the root node
XmlParserUtil.appendChild(mainDom, sourcesDom, null);
MessageBuilder < ? > msgBuilder = MessageBuilder.withPayload(mainDom.asXML());
Message message = msgBuilder.build();
logger.debug("aggregateSources Results after aggregation " + mainDom.asXML());
return message;
}
}
Any thoughts?
Starting with version 4.2 the XPathMessageSplitter is based on the iterator functionality by default:
<xsd:attribute name="iterator" default="true">
<xsd:annotation>
<xsd:documentation>
The iterator mode: 'true' (default) to return an 'java.util.Iterator'
for splitting 'payload', 'false to return a 'java.util.List'.
Note: the 'list' contains transformed nodes whereas with the
'iterator' each node is transformed while iterating.
</xsd:documentation>
</xsd:annotation>
<xsd:simpleType>
<xsd:union memberTypes="xsd:boolean xsd:string" />
</xsd:simpleType>
</xsd:attribute>
Do not overhead the memory with the size interest and pull the data from the target source on demand.
The functionality can be turned off via iterator="false" option.

Delete record on sepecific field value in liferay service builder

I want to delete specific record using Field Name
Table : Dummy Entity
Field Id
Field Name
public void deleteLocation(req, res){
String getLocationName = request.getParameter("locationName");
Location locationToDelete = new LocationImpl();
locationToDelete.setLocationName(getLocationName);
LocationLocalServiceUtil.deleteLocation(locationToDelete);
}
It's not showing me any error but the record doesn't get deleted. Please hep me out.
The simplest way to achieve this is to add <finder> node for that specific field in service.xml, as following (saying Location is your entity name, name is your field name and Name is the name of finder entry in service.xml) and build service:
<column name="name" type="String" />
<finder name="Name" return-type="Collection">
<finder-column name="name" />
</finder>
On successful build, it will create CRUD operations in your service based on that column. Now you can find following methods in your LocationUtil.java:
findByName,
removeByName,
countByName,
Create following (new) method in LocationLocalServiceImpl.java:
public void deleteLocationsByName(String name){
try{
LocationUtil.removeByName(name);
}catch(Exception ex){
// log your exception
}
}
Again, on building service, this method will be available for use in your action class from LocationLocalServiceUtil.java, where you can call it like:
public void deleteLocation(req, res){
String locationName = request.getParameter("locationName");
LocationLocalServiceUtil.deleteLocationsByName(locationName);
}
That's it, you have added custom finder method to your service.
If you want to remove an element by id, you can do it by the "LocalServiceUtil.delete(id)"
If you want to remove an elements by other field than id, you need to do a custom Query for that, you can search in the portal soruce for the file: portal.xml containing this example:
<sql id="com.liferay.portal.service.impl.ResourceBlockLocalServiceImpl.deleteResourceBlock">
<![CDATA[
DELETE FROM
ResourceBlock
WHERE
(referenceCount <= 0) AND
(resourceBlockId = ?)
]]>
</sql>
You can see here how to implement a custom query:
https://dev.liferay.com/develop/tutorials/-/knowledge_base/6-2/developing-custom-sql-queries

MVC 5 Forms authentication retuns null for User.Identity.Name

Authentication fails to authenticate for forms authentication in my MVC 5 application. Page gets redirected correctly, but User.Identity.IsAuthenticated and User.Identity.Name values are empty.
My webconfig,
<system.web>
<authentication mode="Forms">
<forms cookieless="UseCookies" defaultUrl="~/" loginUrl="~/user/signin" name="MYAPPWeb" timeout="21600" slidingExpiration="true"/>
</authentication>
UserController,
[HttpPost]
[AllowAnonymous]
[ValidateAntiForgeryToken]
public ActionResult SignIn(SignInViewModel user)
{
UserDTO userObj;
using (var services = new ServiceFactory())
{
userObj = services.UserManagement.ValidateLoginDetails(ConfigHelper.EnvironmentString, user.TenantName, user.Username, user.Password);
}
string userID = userObj.UserID.ToString();
//FormsAuthentication.RedirectFromLoginPage(userID, user.RememberMe);
FormsAuthentication.SetAuthCookie(userID.ToString(),true);
FormsAuthentication.RedirectFromLoginPage(userID, false); //DO NOT REMEMBER ME
}
HomeController (Default page)
public ActionResult Index()
{
bool x = User.Identity.IsAuthenticated; //false?
string y = User.Identity.Name; //null?
return View();
}
It looks pretty straight forward, am I missing something? Please help!
Note:
When I create the project I selected windows authentication. It created some Owin authenticaiton related configuration cs files (startup.auth.cs). I have removed them and added the above appsetting entry as it is required to stop loading Owin assemblies.
<add key="owin:AutomaticAppStartup" value="false"/>
If your project has Owin authentication by default, it will remove form authentication from the project.
If you see your web config you may see
<remove name="FormsAuthentication" />
configuration.
Simply remove it.
I had the same problem and it solved the issue.

Securing JMXConnectorServerService (jmx-remoting.sar) in JBoss 5.1.0.GA

I've been trying to understand how to secure the JMXConnectorServerService offered by JBoss 5.1.0.GA by default.
Currently, if I paste the following URL into JConsole, I can get to JMX directly without any authentication: service:jmx:rmi:///jndi/rmi://:1290/jmxconnector
Then I did this to secure my JMXInvoker in hopes that that would secure all JMX access: http://objectopia.com/2009/10/01/securing-jmx-invoker-layer-in-jboss/
But, apparently, that doesn't apply to the JMXConnectorServerService. I can still get to JMX using the the above service URL through jconsole.
Then I found out about this feature request that hasn't been accommodated yet: https://issues.jboss.org/browse/JBAS-8159
Now, presently I'm not worried about crazy security measures. This URL is not gonna be exposed to the outside network. So, I just want to see what's the simplest way for me to secure the jmx-remoting.sar with the "jmx-console" security domain?
I could switch to the default MBean server, but apparently, in 5.1.0.GA, that's a pain: https://community.jboss.org/thread/153594
I'd really appreciate any input in this regard.
Thanks!
I don't think that service has been secured, but there is a patch.
For a slightly simpler version, I am going out on a limb here, since I have not tested this on AS 5, but I backported it to AS 4 and it worked ok.
I'm not sure which version you have, exactly, but let's assume it is this one. The EAP version has a slightly more involved version, but the premise is the same. You will need to extend JMXConnectorServerService and JMXConnectorServerServiceMBean.
In this implementation, the code to create the server looks like this:
// create new connector server and start it
connectorServer = JMXConnectorServerFactory.newJMXConnectorServer(url, null, mbeanServer);
In your extension, add the following:
/** The name of the JAAS domain to use for authentication */
protected String jaasDomain = null;
...
/**
* Returns the name of the JAAS domain to use for authentication
* #return the name of a JAAS Domain
*/
public String getJaasDomain() {
return jaasDomain;
}
/**
* Sets the name of the JAAS domain to use for authentication
* #param jaasDomain the JAAS Domain to use for authentication
*/
public void setJaasDomain(String jaasDomain) {
this.jaasDomain = jaasDomain;
}
Now you need to reimplement the start method which adds an environment containing the JAAS domain name you want to authenticate with.
public void start() throws Exception
{
// the address to expose in the urls
String host = System.getProperty("java.rmi.server.hostname");
// check to see if registry already created
rmiRegistry = LocateRegistry.getRegistry(host, registryPort);
if (rmiRegistry != null)
{
try
{
rmiRegistry.list();
}
catch(RemoteException e)
{
log.debug("No registry running at host '" + host +
"', port '" + registryPort + "'. Will create one.");
rmiRegistry = LocateRegistry.createRegistry(registryPort, null, new DefaultSocketFactory(bindAddress));
}
}
else
{
rmiRegistry = LocateRegistry.createRegistry(registryPort, null, new DefaultSocketFactory(bindAddress));
}
String serviceURL = "service:jmx:rmi://" + host + "/jndi/rmi://" + host + ":" + registryPort + jndiPath;
JMXServiceURL url = new JMXServiceURL(serviceURL);
// create new connector server and start it
// ==== NEW AUTH CODE HERE ====
final Map<String, Object> environment = new HashMap<String, Object>();
environment.put("jmx.remote.x.login.config", jaasDomain);
connectorServer = JMXConnectorServerFactory.newJMXConnectorServer(url, environment, mbeanServer);
// ==== NEW AUTH CODE ENDS ====
connectorServer.start();
log.info("JMX Connector server: " + serviceURL);
}
You can optionally validate the JAAS name like this:
/**
* Validates the name of the passed JAAS domain.
* If the name is not valid, a RuntimeException will the thrown.
* #param domain The name of the JAAS domain to validate.
*/
private void validateJaasDomain(String domain) {
try {
new LoginContext(domain);
} catch (Exception e) {
throw new RuntimeException("The JAAS Domain [" + domain + "] could not be loaded", e);
}
}
Add the jaasDomain attribute to the new MBean interface:
/**
* Returns the name of the JAAS domain to use for authentication
* #return the name of a JAAS Domain
*/
public String getJaasDomain();
/**
* Sets the name of the JAAS domain to use for authentication
* #param jaasDomain the JAAS Domain to use for authentication
*/
public void setJaasDomain(String jaasDomain);
Let's assume your new impl is com.vijay.JMXConnectorServerService and the new MBean is com.vijay.JMXConnectorServerServiceMBean; You deployment descriptor would look like this: (using the jmx-console jaas domain, since you probably have that secured....)
<!-- ======================================================== -->
<!-- Example Vijay JMX Remoting Service Configuration file -->
<!-- ======================================================== -->
<server>
<mbean code="com.vijay.JMXConnectorServerService"
name="jboss.remoting:service=JMXConnectorServer,protocol=rmi"
display-name="JMX Connector Server (RMI)">
<attribute name="BindAddress">
<!-- Get the port from the ServiceBindingManager -->
<value-factory bean="ServiceBindingManager" method="getStringBinding"
parameter="jboss.remoting:service=JMXConnectorServer,protocol=rmi"/>
</attribute>
<!-- if comment this out, will use 1099 as default and will conflict -->
<!-- with default JNP (JNDI) port. -->
<attribute name="RegistryPort">
<!-- Get the port from the ServiceBindingManager -->
<value-factory bean="ServiceBindingManager" method="getIntBinding"
parameter="jboss.remoting:service=JMXConnectorServer,protocol=rmi"/>
</attribute>
<!-- the path to which will be bound in rmi registry -->
<!-- the commented value below is the default. -->
<!-- <attribute name="JndiPath">/jmxconnector</attribute> -->
<attribute name="JaasDomain">jmx-console</attribute>
</mbean>
</server>
That's all I have. I hope it is useful to you.

auto login acegi security

Is there a way to avoid form based login in servlet application which uses acegi security module? I want to pass somehow login and password to URL. I tried to call something like this:
GrantedAuthority[] grantedAuthorities = new GrantedAuthority[] {new GrantedAuthorityImpl("ROLE_ADMIN")};
UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken("admin", "passwordofadmin", grantedAuthorities);
WebAuthenticationDetails authdetails = (WebAuthenticationDetails) authentication.getDetails();
HttpSession session = event.getSession();
ProviderManager pm = (ProviderManager)WebApplicationContextUtils.getWebApplicationContext(session.getServletContext()).getBean("authenticationManager");
pm.doAuthentication(authentication);
SecurityContextHolder.getContext().setAuthentication(authentication);
in handler of HttpSessionCreatedEvent event, and I received AuthenticationSuccessEvent event, but then Failure event also received and authentication form displayed.
First you must override UserDetailsService in xml. Something like this:
<bean id="userService" class="com.security.UserSecurityService" >
...
</bean>
Then write your own service.like:
public class UserSecurityService implements UserDetailsService {
public UserDetails loadUserByUsername(String username)
throws UsernameNotFoundException, DataAccessException{
User user =userDAO.findByUsername(username);
GrantedAuthority[] grantedRoles = {new GrantedAuthorityImpl("ROLE_USER")};
secUsr = new User(user.getUsername(), user.getPassword(), true, grantedRoles);
I hope this will be helpful for you

Resources