Thursday, February 18, 2010

DRY up your content using ASP.NET user controls


I was doing a little code-cleanup on an app I support this week.  I was trying to find some places where I could implement the DRY (don't repeat yourself) methodology.  It was fairly easy picking, because this app is leaning a little more toward the RYE (repeat yourself everywhere) methodology.  Anyway, I came up with a way to use ASP.NET User Controls in a project to move some of that repetitive content out of the individual pages, and into a centralized place.

This may not be anything new to anyone, but I had never thought of using a user control for content.  I created two controls, one for some contact information that was used on every page (pointing to different departments in the company), and one to encapsulate some page framework that needed to be slightly different depending on where the application was deployed (I was able to put this logic into the user control and read the location from the web.config).

The contact control renders asp labels to display content on the page, and the framework control renders standard divs.  The code had to be slightly different in the code-behind to search for the controls, but once you set up the controls this way, you wouldn't need to ever change the c# code if you wanted to add a new label or div to the .ascx file.

Anyway, like I said I just came up with this idea earlier this week, but I'm anxious to add it to the toolkit.  I'm already thinking of some more uses for this.  You could perhaps have a 'snippets.ascx' file that had all the reusable content, and enclose each piece in a div.  Then all you'd have to do is call the user control in your app with the name of the div you wanted to render.

i.e. <userControl:Snippets ID="SnippetControl" DivID="WhateverDivIwantToShow" runat="server" />

I'll add the relevant code.  Should be easy to see what I'm talking about.

------------------------------------------------------------------


front-end for user control to deterministically expose asp label controls:

<asp:Label ID="Payroll" Visible="false" runat="server">
<p>
    For questions regarding the content of your documents contact the Payroll Department at 555-5555.
</p>
</asp:Label>

<asp:Label ID="HelpDesk" Visible="false" runat="server">
<p>
    For technical questions or support please contact the Help Desk at 555-5555.
</p>
</asp:Label>


   
c# code-behind for user control:

public partial class Contact : System.Web.UI.UserControl
{
    string strLabelID = string.Empty;

    public string LabelID
    {
        get
        {
            return strLabelID;
        }
        set
        {
            strLabelID = value;
        }
    }

    protected void Page_Load(object sender, EventArgs e)
    {
        foreach (Control ctrl in Controls)
        {
            if (ctrl is Label)
            {
                if (ctrl.ID == strLabelID)
                {
                    ctrl.Visible = true;
                }
            }
        }
    }
}



usage of control:

<ucContact:Contact ID="PayrollContact" LabelID="Payroll" runat="server" />

<ucContact:Contact ID="HelpDeskContact" LabelID="HelpDesk" runat="server" />

------------------------------------------------------------------------------

Another Example:

front-end for user control to deterministically expose generic div elements:

<div id="Header" visible="false" runat="server">
    put stuff in here for the header
</div>

<div id="Footer" visible="false" runat="server">
    put stuff in here for the footer
</div>



c# code-behind for user control:

public partial class PortalFramework : System.Web.UI.UserControl
{
    private string strDivID = string.Empty;

    public string DivID
    {
        get
        {
            return strDivID;
        }
        set
        {
            strDivID = value;
        }
    }

    protected void Page_Load(object sender, EventArgs e)
    {
        foreach (Control ctrl in Controls)
        {
            if (ctrl is HtmlGenericControl)
            {
                if (ctrl.ID == strDivID)
                {
                    ctrl.Visible = true;
                }
            }
        }
    }
}



usage of control:

<ucFramework:PortalFramework ID="PortalFrameworkHeader" runat="server" DivID="Header" />

<ucFramework:PortalFramework ID="PortalFrameworkFooter" runat="server" DivID="Footer" />

Friday, December 18, 2009

Forray into xsl

This summary is not available. Please click here to view the post.

Tuesday, September 22, 2009

TestDisk to the rescue!

Last night I had a serious problem with my netbook. I'm running Ubuntu on a Dell mini with most of the data on an SD card. Anyway, I think the SD card got messed up when the machine went into hibernation, and when I opened the lid I was getting cryptic messages about the drive not being able to mount. I tried the usual tools, fsck, dumpe2fs, gpart, etc. Nothing doing. Everything that was working for other people wasn't working for me... Kept researching the messages I was getting from the various tools:

Block bitmap for group 1 not in group

Bad Magic Number in Superblock

Disk doesn't contain a valid partition table

etc. etc.

The last one ended up being the clue. Found a utility called TestDisk and it had me fixed up in less than 15 minutes.

http://www.cgsecurity.org/wiki/TestDisk_Step_By_Step

It was able to figure out the partitions based on the good data still on the disk. Then it was just a matter of using the tool to rewrite the partition table and I was back in business!

Wednesday, July 22, 2009

Receiving a SAML Response with a Java servlet

As an addendum to my previous post, if you need to receive a SAML Response in a Java servlet using OpenSAML you can use this code. This is, obviously, more likely than needing to create a Response object from an XML file. The 'request' variable is just an input to the processRequest method on the servlet.

import org.opensaml.ws.message.MessageContext;
import org.opensaml.ws.transport.http.HttpServletRequestAdapter;
import org.opensaml.common.binding.BasicSAMLMessageContext;
import org.opensaml.saml2.binding.decoding.HTTPPostDecoder;
import org.opensaml.saml2.core.Response;

//get the message context
MessageContext messageContext = new BasicSAMLMessageContext();
messageContext.setInboundMessageTransport(new HttpServletRequestAdapter(request));
HTTPPostDecoder samlMessageDecoder = new HTTPPostDecoder();
samlMessageDecoder.decode(messageContext);

//get the SAML Response
Response samlResponse = (Response)messageContext.getInboundMessage();

Monday, July 6, 2009

Processing SAML in Java using OpenSAML

I'm currently doing all of my SAML 2.0 work in a .NET environment, but I wanted to verify my SAML in Java too so I created this tester utilizing OpenSAML. It certainly isn't pretty at this point, and I'm certainly not saying it represents any best-practices, but I'm going to post it in its current state because I think it illustrates some useful things. It's basically just unmarshalling xml to an OpenSAML response object, verifying the signature on the response, and decrypting an assertion. Nothing terribly mind-blowing, but it might prove useful to someone.

import org.w3c.dom.Document;
import org.w3c.dom.Element;

import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;

import java.util.List;

import javax.xml.namespace.QName;
import javax.xml.validation.Schema;

import java.security.KeyFactory;
import java.security.KeyStore;
import java.security.PublicKey;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
import java.security.interfaces.RSAPrivateKey;
import java.security.spec.X509EncodedKeySpec;

import org.opensaml.DefaultBootstrap;
import org.opensaml.common.xml.SAMLSchemaBuilder;
import org.opensaml.saml2.core.Assertion;
import org.opensaml.saml2.core.Attribute;
import org.opensaml.saml2.core.AttributeStatement;
import org.opensaml.saml2.core.Response;
import org.opensaml.saml2.encryption.Decrypter;
import org.opensaml.xml.Configuration;
import org.opensaml.xml.XMLObject;
import org.opensaml.xml.encryption.DecryptionException;
import org.opensaml.xml.encryption.InlineEncryptedKeyResolver;
import org.opensaml.xml.io.Unmarshaller;
import org.opensaml.xml.parse.BasicParserPool;
import org.opensaml.xml.security.keyinfo.StaticKeyInfoCredentialResolver;
import org.opensaml.xml.security.x509.BasicX509Credential;
import org.opensaml.xml.signature.Signature;
import org.opensaml.xml.signature.SignatureValidator;
import org.opensaml.xml.validation.ValidationException;


public class Tester
{
public static void main(String[] args)
{
try
{
//initialize the opensaml library
DefaultBootstrap.bootstrap();

Schema schema = SAMLSchemaBuilder.getSAML11Schema();

//get parser pool manager
BasicParserPool parserPoolManager = new BasicParserPool();
parserPoolManager.setNamespaceAware(true);
parserPoolManager.setIgnoreElementContentWhitespace(true);
parserPoolManager.setSchema(schema);

//grab the xml file
File xmlFile = new File("C:\\Documents and Settings\\kgellis\\My Documents\\Eclipse\\Workspace\\MyOpenSamlTester\\Files\\Raw_AssertionEncrypted.xml");

//parse xml file
FileInputStream fileInputStream = new FileInputStream(xmlFile);
InputStream inputStream = fileInputStream;
Document document = parserPoolManager.parse(inputStream);
Element metadataRoot = document.getDocumentElement();

QName qName= new QName(metadataRoot.getNamespaceURI(), metadataRoot.getLocalName(), metadataRoot.getPrefix());

//get an unmarshaller
Unmarshaller unmarshaller = Configuration.getUnmarshallerFactory().getUnmarshaller(qName);

//unmarshall using the document root element
Response response = (Response)unmarshaller.unmarshall(metadataRoot);

//we have the xml unmarshalled to a response object
System.out.println("Response object created");
System.out.println("Issue Instant: " + response.getIssueInstant().toString());
System.out.println("Signature Reference ID: " + response.getSignatureReferenceID().toString());

//grab the certificate file
File certificateFile = new File("C:\\Documents and Settings\\kgellis\\My Documents\\Eclipse\\Workspace\\MyOpenSamlTester\\Files\\Con-wayPublicKey.cer");

//get the certificate from the file
InputStream inputStream2 = new FileInputStream(certificateFile);
CertificateFactory certificateFactory = CertificateFactory.getInstance("X.509");
X509Certificate certificate = (X509Certificate)certificateFactory.generateCertificate(inputStream2);
inputStream2.close();

//pull out the public key part of the certificate into a KeySpec
X509EncodedKeySpec publicKeySpec = new X509EncodedKeySpec(certificate.getPublicKey().getEncoded());

//get KeyFactory object that creates key objects, specifying RSA
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
System.out.println("Security Provider: " + keyFactory.getProvider().toString());

//generate public key to validate signatures
PublicKey publicKey = keyFactory.generatePublic(publicKeySpec);

//we have the public key
System.out.println("Public Key created");

//create credentials
BasicX509Credential publicCredential = new BasicX509Credential();

//add public key value
publicCredential.setPublicKey(publicKey);

//create SignatureValidator
SignatureValidator signatureValidator = new SignatureValidator(publicCredential);

//get the signature to validate from the response object
Signature signature = response.getSignature();

//try to validate
try
{
signatureValidator.validate(signature);
}
catch (ValidationException ve)
{
System.out.println("Signature is NOT valid.");
System.out.println(ve.getMessage());
return;
}

//no validation exception was thrown
System.out.println("Signature is valid.");

//start decryption of assertion

//grab the KeyStore file
File keyStoreFile = new File("C:\\Documents and Settings\\kgellis\\My Documents\\Eclipse\\Workspace\\MyOpenSamlTester\\Files\\WWCPrivateKey.jks");

KeyStore keyStore = KeyStore.getInstance("JKS");

//load up a KeyStore
keyStore.load(new FileInputStream(keyStoreFile), "!c3c0ld".toCharArray());

RSAPrivateKey privateKey = (RSAPrivateKey) keyStore.getKey("pvktmp:bd5ba0e0-9718-48ea-b6e6-32cd9c852d76", "!c3c0ld".toCharArray());

//we have the private key
System.out.println("Private Key created");
System.out.println("Private Key Algorithm: " + privateKey.getAlgorithm());

//create the credential
BasicX509Credential decryptionCredential = new BasicX509Credential();
decryptionCredential.setPrivateKey(privateKey);

StaticKeyInfoCredentialResolver skicr = new StaticKeyInfoCredentialResolver(decryptionCredential);

//create a decrypter
Decrypter decrypter = new Decrypter(null, skicr, new InlineEncryptedKeyResolver());

//decrypt the first (and only) assertion
Assertion decryptedAssertion;

try
{
decryptedAssertion = decrypter.decrypt(response.getEncryptedAssertions().get(0));
}
catch (DecryptionException de)
{
System.out.println("Assertion decryption failed.");
System.out.println(de.getMessage());
return;
}

System.out.println("Assertion decryption succeeded.");
System.out.println("Assertion ID: " + decryptedAssertion.getID());

//loop through the nodes to get what we want
List<AttributeStatement> attributeStatements = decryptedAssertion.getAttributeStatements();
for (int i = 0; i < attributeStatements.size(); i++)
{
List<Attribute> attributes = attributeStatements.get(i).getAttributes();
for (int x = 0; x < attributes.size(); x++)
{
String strAttributeName = attributes.get(x).getDOM().getAttribute("Name");

List<XMLObject> attributeValues = attributes.get(x).getAttributeValues();
for (int y = 0; y < attributeValues.size(); y++)
{
String strAttributeValue = attributeValues.get(y).getDOM().getTextContent();
System.out.println(strAttributeName + ": " + strAttributeValue);
}
}
}
}
catch (Exception ex)
{
ex.printStackTrace();
}
}
}

Friday, May 22, 2009

Passing a variable to Openquery in SQL Server 2005

You'd think that passing a variable to Openquery in SQL Server 2005 would be easy. It isn't. The parser won't parse a string like you think it would. Instead you need to do something like this (and those are all single-quotes):

DECLARE @TSQL varchar(8000), @VAR char(50)
SELECT @VAR = 'XXXXX'
SELECT @TSQL = 'SELECT * FROM OPENQUERY(ConnectionName,''SELECT SomeField FROM SomeTable WHERE AnotherField = ''''' + @VAR + ''''''')'
EXEC (@TSQL)

Ugly, but it works.

Thursday, May 14, 2009

Creating a free public/private key pair in Windows

I recently had to test something with public and private keys. You don't want to have to pay for certificates for testing. Free is better. These commands came in very handy so I'm documenting them here so I don't forget...

Go to this directory (or the equivalent depending on your VS install):
C:\Program Files\Microsoft SDKs\Windows\v6.0A\Bin\

makecert -r -pe -n "cn=kevnls" -b 01/01/2008 -e 01/01/2020 -sky exchange -sv kevnls.pvk kevnls.cer

pvk2pfx -pvk kevnls.pvk -spc kevnls.cer -pfx kevnls.pfx -po somepassword

Edit: If you need a java keystore (.jks) instead of a .pvk file you can do this using the keytool in the jre (usually in C:\Program Files\Java\jre6\bin\).


./keytool -genkey -keyalg RSA -alias somealias -keystore kevnls.jks -storepass somepassword -validity 7300 -keysize 2048

./keytool -export -keystore keystore.jks -alias somealias -file kevnls.cer