Injecting a File in Spring Java Config - spring-security

I am trying to configure SAML authentication using Spring's SAML extension. While trying it in the annotation way using Java Configuration. I have a requirement of getting the IDP metadata file and the SP metadata file to create the metadataManager bean.
Here is the relevant configuration:
#Bean(name="idpMetadata")
public ExtendedMetadataDelegate idpMetaData(){
FilesystemMetadataProvider metadataProvider = null;
try {
metadataProvider = new FilesystemMetadataProvider(idpMetadataFile);
metadataProvider.setParserPool(parserPool());
}
catch (MetadataProviderException e) {
e.printStackTrace();
}
ExtendedMetadataDelegate metaDataDelegate =
new ExtendedMetadataDelegate(metadataProvider, new ExtendedMetadata());
return metaDataDelegate;
}
#Bean(name="spMetadata")
public ExtendedMetadataDelegate spMetaData(){
FilesystemMetadataProvider metadataProvider = null;
try {
metadataProvider = new FilesystemMetadataProvider(spMetadataFile);
metadataProvider.setParserPool(parserPool());
}
catch (MetadataProviderException e) {
e.printStackTrace();
}
ExtendedMetadata extendedMetadata = new ExtendedMetadata();
extendedMetadata.setLocal(true);
extendedMetadata.setAlias("defaultAlias");
extendedMetadata.setSecurityProfile("metaiop");
extendedMetadata.setSslSecurityProfile("pkix");
extendedMetadata.setRequireArtifactResolveSigned(true);
extendedMetadata.setRequireLogoutRequestSigned(true);
extendedMetadata.setRequireLogoutResponseSigned(false);
extendedMetadata.setIdpDiscoveryEnabled(false);
ExtendedMetadataDelegate metaDataDelegate =
new ExtendedMetadataDelegate(metadataProvider, extendedMetadata);
return metaDataDelegate;
}
My problem is I am not able to get the file content here. The spMetadataFile and the idpMetadataFile are null. I am not sure how can I inject or get old of these files if stored in the classpath of the project.
Please help.

This code works fine on my own SP-implementation:
#Bean
#Qualifier("yourMetadataProvider")
public ExtendedMetadataDelegate yourMetadataProvider()
throws MetadataProviderException, IOException {
String path = "<metadata_path>";
FilesystemMetadataProvider filesystemMetadataProvider = new FilesystemMetadataProvider(
new File(path));
filesystemMetadataProvider.setParserPool(parserPool());
ExtendedMetadataDelegate emd = new ExtendedMetadataDelegate(
filesystemMetadataProvider, new ExtendedMetadata());
// Your config
emd.setLocal(true);
emd.setAlias("defaultAlias");
emd.setSecurityProfile("metaiop");
emd.setSslSecurityProfile("pkix");
emd.setRequireArtifactResolveSigned(true);
emd.setRequireLogoutRequestSigned(true);
emd.setRequireLogoutResponseSigned(false);
emd.setIdpDiscoveryEnabled(false);
return emd;
}
Be careful when setting the path of your metadata file.

Related

using wss4jsecurityinterceptor for spring security- Configuring securement for signature and encryption with two keys

I am trying to add interceptors for securing spring-ws by reading this tutorial at https://memorynotfound.com/spring-ws-certificate-authentication-wss4j/
I need to use two seperate public-private keys (one for signing,second for encryption) in a single keystore(server.jks- file).But i am not able to configure the security interceptor.
It works fine as in example if use a single keystore , but how should i set the following when seperate keys for signing and encryption
#Bean
public KeyStoreCallbackHandler securityCallbackHandler(){
KeyStoreCallbackHandler callbackHandler = new KeyStoreCallbackHandler();
callbackHandler.setPrivateKeyPassword("changeit");
return callbackHandler;
}
#Bean
public Wss4jSecurityInterceptor securityInterceptor() throws Exception {
Wss4jSecurityInterceptor securityInterceptor = new Wss4jSecurityInterceptor();
// validate incoming request
securityInterceptor.setValidationActions("Timestamp Signature Encrypt");
securityInterceptor.setValidationSignatureCrypto(getCryptoFactoryBean().getObject());
securityInterceptor.setValidationDecryptionCrypto(getCryptoFactoryBean().getObject());
securityInterceptor.setValidationCallbackHandler(securityCallbackHandler());
// encrypt the response
securityInterceptor.setSecurementEncryptionUser("client-public");
securityInterceptor.setSecurementEncryptionParts("{Content}{https://memorynotfound.com/beer}getBeerResponse");
securityInterceptor.setSecurementEncryptionCrypto(getCryptoFactoryBean().getObject());
// sign the response
securityInterceptor.setSecurementActions("Signature Encrypt");
securityInterceptor.setSecurementUsername("server");
securityInterceptor.setSecurementPassword("changeit");
securityInterceptor.setSecurementSignatureCrypto(getCryptoFactoryBean().getObject());
return securityInterceptor;
}
#Bean
public CryptoFactoryBean getCryptoFactoryBean() throws IOException {
CryptoFactoryBean cryptoFactoryBean = new CryptoFactoryBean();
cryptoFactoryBean.setKeyStorePassword("changeit");
cryptoFactoryBean.setKeyStoreLocation(new ClassPathResource("server.jks"));
return cryptoFactoryBean;
}
For encryption we have the method setSecurementEncryptionUser, but how do we configure setValidationDecryptionCrypto and setValidationSignatureCrypto with the alias to decrypt/validate
Could you try having 2 securityInterceptor with 2 keystores? One for signature and one for encryption. Then add both interceptors to the list of interceptors.
#Override
public void addInterceptors(List<EndpointInterceptor> interceptors) {
try {
interceptors.add(signatureSecurityInterceptor());
interceptors.add(encryptionSecurityInterceptor());
} catch (Exception e) {
throw new RuntimeException("could not initialize security interceptor");
}
}

Spring Boot with Neo4J JDBC and MySQL

My Spring Boot Application is secured by Spring Security OAuth2. The userdata is stored in a SQL-database. I followed here royclarkson's Oauth protected REST service. This project works with Spring Data JPA. This works fine.
https://github.com/royclarkson/spring-rest-service-oauth
But now I want to implement my Neo4J Configuration to get data from my Neo4J-Database via Neo4J-JDBC (JDBC-template). Here I followed this GitHub project:
https://github.com/neo4j-examples/movies-java-spring-boot-jdbc
As a standalone application it works, but if I put this two projects togehter, I get this Exception:
HibernateJpaAutoConfiguration.class]: Invocation of init method failed;
nested exception is org.hibernate.HibernateException:
Unable to determine Dialect to use [name=Neo4j, majorVersion=3];
user must register resolver or explicitly set 'hibernate.dialect'
My Neo4jConfig.java looks like this:
#Configuration
public class Neo4jConfig {
//NEO4J Server Implementation via JDBC
private static final String NEO4J_URL = System.getProperty("NEO4J_URL","jdbc:neo4j://localhost:7474");
private static final String NEO4J_USER = System.getProperty("NEO4J_USER","neo4j");
private static final String NEO4J_PASSWORD = System.getProperty("NEO4J_PASSWORD","neo4j");
#Bean
public DataSource dataSource() {
return new DriverManagerDataSource(NEO4J_URL, NEO4J_USER, NEO4J_PASSWORD);
}
public Neo4jConfig(){
}
public String getNeo4JURL(){
return NEO4J_URL;
}
}
TripController.java
import hello.data.Trip;
#RestController
public class TripController {
#Autowired
JdbcTemplate template;
public static final RowMapper<Trip> TRIP_ROW_MAPPER = new RowMapper<Trip>() {
public Trip mapRow(ResultSet rs, int rowNum) throws SQLException {
return new Trip(rs.getString("tripname"),rs.getInt("slots"), rs.getInt("to_date"), rs.getInt("from_date"));
}
};
String SEARCH_TRIPS_QUERY =
" MATCH (t:Trip)\n" +
" RETURN t.tripname as tripname, t.slots as slots, t.to_date as to_date, t.from_date as from_date";
#RequestMapping(path = "/alltrips", method = RequestMethod.GET)
public List<Trip> alltrips() {
return template.query(SEARCH_TRIPS_QUERY, TRIP_ROW_MAPPER);
}
}
I hope you guys understand my question. I know, I am a really newone at Spring, but I hope anyone can help me :)
This is happening because hibernate does not find any dialect for Neo4J as Neo4j is not RDBMS database and dialect is not provided by default. You can use Hibernate OGM (search and include it in pom.xml), and then use following configuration to configure Entitymanager and Transaction manager
#Configuration
#EnableJpaRepositories(basePackages = {
"your repository packages" }, entityManagerFactoryRef = "n4jEntityManager", transactionManagerRef = "n4jTxnManager")
public class DatabaseConfiguration {
#Bean(name = "n4jEntityManager")
public LocalContainerEntityManagerFactoryBean entityManager() {
Map<String, Object> properties = new HashMap<String, Object>();
properties.put("javax.persistence.transactionType", "resource_local");
properties.put("hibernate.ogm.datastore.provider","neo4j");
properties.put("hibernate.ogm.datastore.host","localhost");
properties.put("hibernate.ogm.datastore.port","7474");
properties.put("hibernate.ogm.datastore.database", "your database");
properties.put("hibernate.ogm.datastore.create_database", "true or false");
LocalContainerEntityManagerFactoryBean entityManager = new LocalContainerEntityManagerFactoryBean();
entityManager.setPackagesToScan("your domain packages");
entityManager.setPersistenceUnitName("n4jPU");
entityManager.setJpaPropertyMap(properties);
entityManager.setPersistenceProviderClass(HibernateOgmPersistence.class);
return entityManager;
}
#Bean(name = "n4jTxnManager")
public PlatformTransactionManager txnManager() {
JpaTransactionManager transactionManager = new JpaTransactionManager();
transactionManager.setEntityManagerFactory(mongoEntityManager().getObject());
return transactionManager;
}
}
But I suggest, to remove Hibernate altogether if you are not going to use RDBMS and will only be using Neo4j. Spring data has good support for NoSQL databases and Entities can be defined using annotations like #NodeEntity and #GraphId

Apache Camel: How to rebuild the url based on the old one or the header

I am using route on the camel that starts a server that is used as an access point to request, re-directions, gateway to database, etc.
And I want to redirect a get request to another service that is in another server and compose the url based on the request. I have made a processor that gets the header and puts in the new url. However the new url does not get executed...
Here is the code:
CamelContext context = new DefaultCamelContext();
ConnectionFactory connectionFactory =
new ActiveMQConnectionFactory("vm://localhost?create=false");
context.addComponent("activemq", JmsComponent.jmsComponentAutoAcknowledge(connectionFactory));
context.start();
Processor Redir = new RedirectProcess();
from("jetty:http://localhost:8080/Middleware")
.choice()
.when(header("redir")).process(Redir)
.end()
And the Processor
public class RedirectProcess implements Processor {
String value = null;
String Head;
public void process(Exchange inExchange) throws Exception {
Head = inExchange.getIn().getHeader("redir").toString();
CamelContext camelContext = new DefaultCamelContext();
camelContext.addRoutes(route());
camelContext.start();
ProducerTemplate template = camelContext.createProducerTemplate();
template.sendBody("direct:start", "Hello Camel");
System.out.println(Head);
}
public RouteBuilder route() {
return new RouteBuilder() {
public void configure() {
// you can configure the route rule with Java DSL here
System.out.println("Passed HERE!");
from("direct:start")
.to("http://localhost:8081/FunctLayer/tool/start/tool/" + Head + "");
}
};
}
}
It does not work like this. Don't try to create contexts nor routes in runtime. Use Recipient List pattern (http://camel.apache.org/recipient-list.html).
Your code would look like:
CamelContext context = new DefaultCamelContext();
ConnectionFactory connectionFactory = new ActiveMQConnectionFactory("vm://localhost?create=false");
context.addComponent("activemq",JmsComponent.jmsComponentAutoAcknowledge(connectionFactory));
context.start();
from("jetty:http://localhost:8080/Middleware")
.choice()
.when(header("redir"))
.recipientList(simple("http://localhost:8081/FunctLayer/tool/start/tool/${header.redir}"))
.end()

Overwrite pdf file without "file in use" or "access denied" exceptions in asp.net mvc

We have asp.net mvc web application. We are serving pdf file via FileContentResult in controller:
return File("x.pdf", "application/pdf", Server.UrlEncode("x.pdf"));
How can we overwrite PDF file on server side without "file in use" exceptions.
There will be uploading interface but the question is not related with interface. How can I safely overwrite the file. Safe means
Nobody gets error during overwriting process (Some of the users may read during overwriting process)
Overwrite without error ("file in use" or other exceptions)
EDIT
There is good advice from frikinside but FilePathResult does not have FileShare option
public class FilePathResult : FileResult
{
public string FileName
{
get;
private set;
}
public FilePathResult(string fileName, string contentType) : base(contentType)
{
if (string.IsNullOrEmpty(fileName))
{
throw new ArgumentException(MvcResources.Common_NullOrEmpty, "fileName");
}
this.FileName = fileName;
}
protected override void WriteFile(HttpResponseBase response)
{
response.TransmitFile(this.FileName);
}
}
So the question is : How can we transmitFile with "FileMode.Open, FileAccess.Read, FileShare.ReadWrite" option?
When you upload the file you could implement a lock on the file.
public class SafeFileUploader
{
private object file_lock = new object();
private static SafeFileUploader instance;
private SafeFileUploader() { }
public static SafeFileUploader GetInstance
{
get
{
if (instance == null)
{
instance = new SafeFileUploader();
}
return instance;
}
}
public static SafeFileUploadProcess(string path)
{
lock (file_lock)
{
//FileUploadProcess
}
}
}
UPDATED 2.0
Based on your comment, I'm updating this answer to offer a not exclusive reading method.
using (FileStream fs = new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
{
using (StreamReader sr = new StreamReader(fs, Encoding.Default))
{
// FileReadingProcess
}
}
Using FileShare.ReadWrite will permit opening a stream allowing reading and writing by another process.
UPDATED 3.0
If you are using FilePathResult from MVC to returning the file, you can always use a stream as parameter instead of path to ensure FileAccess and FileShare are correct.
return File(new FileStream("x.pdf", FileMode.Open, FileAccess.Read, FileShare.ReadWrite), "application/pdf", Server.UrlEncode("x.pdf"));

write Junit for JNDI

I used JNDI connection in my application and it is working. But I need to write Junits to test the connection. We dont use any spring framework. This is the method i wrote to get JNDI connection.
public Connection getConnection() throws SQLException {
DataSource ds = null;
InitialContext ic = null;
Connection con = null;
try {
ic = new InitialContext();
ds = (DataSource) ic.lookup("java:/DBs");
con = ds.getConnection();
return con;
} catch (Exception e) {
throw new SQLException(e);
}
}
You can make use of the SimpleNamingContextBuilder that comes with the spring-test library. You can use this even if you aren't using Spring as it isn't Spring specific.
Below is an example of setting up a JNDI connection in the #Before of the JUnit test.
package com.example;
import org.springframework.jdbc.datasource.DriverManagerDataSource;
import org.springframework.mock.jndi.SimpleNamingContextBuilder;
public class SomeTest
{
#Before
public void contextSetup () throws Exception
{
SimpleNamingContextBuilder builder = SimpleNamingContextBuilder.emptyActivatedContextBuilder();
DriverManagerDataSource dataSource = new DriverManagerDataSource("org.hsqldb.jdbcDriver", "jdbc:hsqldb:mem:testdb", "sa", "");
builder.bind("java:comp/env/jdbc/ds1", dataSource);
builder.bind("java:comp/env/jdbc/ds2", dataSource);
}
#Test
public void testSomething () throws Exception
{
/// test with JNDI
}
}
UPDATE: This solution also uses Spring's DriverManagerDataSource. If you want to use that you will also need the spring-jdbc library. But you don't have to use this, you can create any object you like and put it into the SimpleNamingContextBuilder. For example, a DBCP connection pool, a JavaMail Session, etc.
OK. After lot of searching i found a solution.And it is working for me. I want to share this to everybody. Hope this thing might help people who are having the same issue. Please add the below code.Add ojdb6.jar and naming-common-4.1.31.jar in your test libraries
#BeforeClass
public static void setUpClass() throws Exception {
try {
System.setProperty(Context.INITIAL_CONTEXT_FACTORY,
"org.apache.naming.java.javaURLContextFactory");
System.setProperty(Context.URL_PKG_PREFIXES,"org.apache.naming");
InitialContext ic = new InitialContext();
ic.createSubcontext("java:");
ic.createSubcontext("java:/comp");
ic.createSubcontext("java:/comp/env");
ic.createSubcontext("java:/comp/env/jdbc");
OracleConnectionPoolDataSource ocpds = new OracleConnectionPoolDataSource();
ocpds.setURL("your URL");
ocpds.setUser("your username");
ocpds.setPassword("your password");
ic.bind("java:/yourJNDIName", ocpds);
} catch (NamingException ex) {
Logger.getLogger(yourTesTClass.class.getName()).log(Level.SEVERE, null, ex);
}
}
If this is running outside the app server, then you'll likely need to supply parameters to the call for the InitialContext. But also realize that many DataSource implementations are not serializable so they won't work outside the container.
What you're writing is an integration test and it should be run in the container.

Resources