CSS

Wednesday, August 25, 2021

403 Response to My Developer Box

So I had a perfectly working setup. I could call my machine's end point no problem. When I had a outside service use the service as a callback they got 403 Unauthorized. 

 It looks like it was my ISP. I'm guessing this since the call never hit my Apache server. 

 How I fixed it. 

 tldr; I created an Apache Server in AWS and proyied through there. I have a AWS enviornment which includes a Windows RRAS VPN. I connect to AWS through the VPN. 

I am just going to give an overview of what I did.  I expect you to know about Windows VPN and Linux.

  Steps 

 since I am using Windows RRAS VPN I can NAT all http calls to my machine.

Go to your domain server and go to the Dial-up and set a static IP address for yourself.

Go to Routing and Remote Access Manager on the VPN server.


Under Services and Port Tab choose HTTP  set the destination IP to the one you choose for yourself.

Make sure your VPN server is in a security group that allows http access.

In AWS \create a micro instance using your favorite Linux.

ssh into your machine

Install Apache

enable mod proxy

sudo a2nenmod proxy


Since you are NATed througj the VPN server you need to setup a proxy to it


ProxyPass "/"  "http://10.0.0.204/"

<Location "/.well-known/">

    ProxyPass "!"

</Location>


Make sure you exclude the .well-known directory so you can get an SSL Cert from Letsencypt.


Have fun





Thursday, March 5, 2020

A poor mans CNAME using /etc/hosts

I did not want to set dnsmasq to setup a couple of CNAMEs. So I wrote the following little script to do the work. I run it at boot using root's crontab @reboot
 
You need to put a placeholder in /etc/hosts.
127.0.0.1 search.me
The bash script
lookup=search.me
ip=`dig google.com +short | grep '^[.0-9]*$'`
sed -i -r "s/([0-9]{1,3}\.){3}[0-9]{1,3}\s+$lookup/$ip $lookup/g"  /etc/hosts

Tuesday, January 30, 2018

Programatically get files protected by a CAS SSO Server

My company uses Apereo CAS as a single sign on server.  It also protects our files from being download unless a user is logged in.  I have a number of background tasks that run that need to make some HTTP calls to one of our systems to pages that are protected by CAS

Whats the answer?

I decided to go with Basic Authentication.  You cannot use the proxy mechanism since you don;t have a logged in user.

Enable Basic Authentication on Server

You will need to rebuild your CAS overlay war. Add the following dependency to your pom.xml file.

<dependency>
  <groupid>org.apereo.cas</groupid>
  <artifactid>cas-server-support-basic</artifactid>
  <version>${cas.version}</version>
</dependency> 


Java Utility Class

This class sets up a Apache Http Client.  It is also used to set the headers on the request.  I found that preemptively sending the Basic Authentication headers was the way to get it to work.

package org.yfu.security;

import java.io.IOException;
import java.nio.charset.Charset;
import java.security.KeyManagementException;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.util.Base64;

import org.apache.http.HttpHeaders;
import org.apache.http.auth.AuthScope;
import org.apache.http.auth.UsernamePasswordCredentials;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.CookieStore;
import org.apache.http.client.CredentialsProvider;
import org.apache.http.client.HttpClient;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.conn.ssl.SSLContextBuilder;
import org.apache.http.conn.ssl.TrustSelfSignedStrategy;
import org.apache.http.impl.client.BasicCookieStore;
import org.apache.http.impl.client.BasicCredentialsProvider;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.message.AbstractHttpMessage;

public class CasBasicAuthUtil {
 
 private String username;
 private String password;
 
 

 public CasBasicAuthUtil(String username, String password) {
  super();
  this.username = username;
  this.password = password;
 }

 public HttpClient getHttpClient() throws ClientProtocolException, IOException, 
                  NoSuchAlgorithmException, KeyStoreException, KeyManagementException {
  // Create a local instance of cookie store
  CookieStore cookieStore = new BasicCookieStore();
   SSLContextBuilder builder = new SSLContextBuilder();
      builder.loadTrustMaterial(null, new TrustSelfSignedStrategy());
      SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(
              builder.build());
      CredentialsProvider provider = new BasicCredentialsProvider();
      UsernamePasswordCredentials credentials
       = new UsernamePasswordCredentials(username, password);
      provider.setCredentials(AuthScope.ANY, credentials);
      CloseableHttpClient httpclient = HttpClients.custom().setSSLSocketFactory(
              sslsf)
        .setDefaultCredentialsProvider(provider)
        .setDefaultCookieStore(cookieStore).build();
  
  

  
  return httpclient;
  
  
  
 }
 
 public void addHeaders(AbstractHttpMessage request) {
  String auth = username + ":" + password;
  byte[] encodedAuth = Base64.getEncoder().encode(
    auth.getBytes(Charset.forName("ISO-8859-1")));
  String authHeader = "Basic " + new String(encodedAuth);
  request.setHeader(HttpHeaders.AUTHORIZATION, authHeader);

 }
 
}

How to use the Utility


                CasBasicAuthUtil casUtil = new CasBasicAuthUtil("Usename", "Password");
  HttpClient client = casUtil.getHttpClient();
  final String url = getDocUrl(fileId);
  cat.debug(url);
  HttpGet httpGet = new HttpGet(url);
  casUtil.addHeaders(httpGet);
  HttpResponse response = client.execute(httpGet);
  final int statusCode = response.getStatusLine().getStatusCode();
  if (statusCode == 200) {
   //  we got the file.  Do something with it.
  } 

Tuesday, October 31, 2017

Move dropbox directory on Linux using the command line

Short Answer

You can't.  All the stuff on the internet is real old.   I worked on this for 10 hours and here is my answer.

How to get the directory where you want

This is only really useful if you want to move the dropbox directory to a filesystem other then the one your users are on.

Create a user whose home directory is where you want the Dropbox directory to be.  The Dropbox directory is going to end up under this user's home directory.  

Why is this better then a symbolic link?

It is better than a symbolic link since because Dropbox uses OS level file notifications calls to decide what to sync.  These do not work through a symbolic link.  If you just make a link called Dropbox and point it to another filesystem your files will not be synced.  You can change and create files through a symbolic link.  Dropbox needs to have a real link to work.

Tuesday, June 27, 2017

Fix Greeter Login panel on Ubuntu 17.04

This works with all flavors of Linux that use LightDM as their greeter.

When my laptop was in its docking station, the login prompt would not display.  I guess it was displaying on the closed laptop display.

Create a file /opt/sbin/set-prime-mon

Contents:
#!/bin/sh
# Set prime monitor to left most
LOG=/var/log/set-prime-mon.log
# Remove any previous logs
rm -f $LOG
output=$(xrandr | grep -E " connected (primary )?[1-9]+" | grep "+0+0" | sed -e "s/\([A-Z0-9]\+\) connected.*/\1/")
echo $output >> $LOG 2>&1
if [ -n $output ]; then
 echo "setting prime to $output" >> $LOG 2>&1
 xrandr --output $output --primary
fi

Create a file /etc/lightdm/lightdm.conf.d/99-setprime.sh

Contents:
display-setup-script=/opt/sbin/set-prime-mon

Wednesday, April 19, 2017

Stopping new Icon when I launch a java appication from Gnome or Unity

So I had successfully created a .desktop file to launch Eclipse from Gnome.  I also found it no problem  making it a favorite.  The problem I was having was every time I launched Eclipse I ended up with 2 icons.  The Favorite and one for the running process.  The trick to making not getting this is to make sure the .desktop name matches the xwindows WM_CLASS property. You can get this value by running:

 xprop WM_CLASS 

Next click on the window of the Java application you are interested in.  In the case of Eclipse the value is "Eclipse" so the file needs to be named Eclipse.desktop.

Thursday, March 30, 2017

Java Base64 OutputStream cutting off characters

This took me a while to figure out. I am using a Outputstream to write create a piece of XML.  One of the elements needed to be Base64 encoded.  I wrapped my outputstring using java.util.Base64.wrap.  I did not close the Base64 OutputStream.  It is not really clear but the close of this stream is when it takes care of padding,

Bad Code

// out is a FileOutputStream 
final Base64.Encoder encoder = Base64.getMimeEncoder(); 
final OutputStream clob = encoder.wrap(out); 
IOUtils.copy(in, clob, Charset.forName("UTF-8")); 
// No close of clob Just went and kept writing to out 

Good Code

// out is a FileOutputStream 
final Base64.Encoder encoder = Base64.getMimeEncoder(); 
final OutputStream clob = encoder.wrap(
      new CloseShieldOutputStream(out)); // Use nice Apache IO Wrapper that does                        // not chain close 
IOUtils.copy(in, clob, Charset.forName("UTF-8")); 
clob.close(); // this forces out the padding

Wednesday, November 19, 2014

Fix errors with IBM Data Studio and DB2 10.4 on Linux Mint 17.1

I was getting the following errors every time I clicked on something with my newly installed IBM Data Studio:


com.ibm.db2.jcc.am.SqlException: DB2 SQL Error: SQLCODE=-805, SQLSTATE=51002, SQLERRMC=NULLID.SYSSH200 0X5359534C564C3031, DRIVER=4.18.60 at com.ibm.db2.jcc.am.kd.a(Unknown Source) at com.ibm.db2.jcc.am.kd.a(Unknown Source) at com.ibm.db2.jcc.am.kd.a(Unknown Source) at com.ibm.db2.jcc.am.bp.c(Unknown Source) at com.ibm.db2.jcc.t4.bb.p(Unknown Source) at com.ibm.db2.jcc.t4.bb.h(Unknown Source) at com.ibm.db2.jcc.t4.bb.b(Unknown Source) at com.ibm.db2.jcc.t4.p.a(Unknown Source) at com.ibm.db2.jcc.t4.vb.i(Unknown Source) at com.ibm.db2.jcc.am.bp.kb(Unknown Source) at com.ibm.db2.jcc.am.cp.xc(Unknown Source) at com.ibm.db2.jcc.am.cp.b(Unknown Source) at com.ibm.db2.jcc.am.cp.kc(Unknown Source) at com.ibm.db2.jcc.am.cp.executeQuery(Unknown Source) at com.ibm.datatools.uom.ConnectionService.getDB2Instance(Unknown Source) at com.ibm.datatools.dse.db2.luw.ui.internal.databases.listview.DB2ConnectionDetailsProvider.getInstanceName(Unknown Source) at com.ibm.datatools.uom.ui.internal.databases.listview.ObjectListDatabasesPropertiesProvider$ConnectionProfilePropertyValueProvider.getPropertyValue(Unknown Source) ...

I did a bind and it cleared up.


db2 terminate 
db2 CONNECT TO dbname user USERID using PASSWORD 
db2 BIND path/db2schema.bnd BLOCKING ALL GRANT PUBLIC SQLERROR CONTINUE 
db2 BIND path/@db2ubind.lst BLOCKING ALL GRANT PUBLIC ACTION ADD 
db2 BIND path/@db2cli.lst BLOCKING ALL GRANT PUBLIC ACTION ADD 
db2 terminate

Here is where I got the commands from: http://www-01.ibm.com/support/knowledgecenter/SSEPGG_10.5.0/com.ibm.db2.luw.qb.server.doc/doc/t0024970.html?cp=SSEPGG_10.5.0%2F2-2-0-4-2

Wednesday, March 26, 2014

Java Epoch to TIMESTAMP function

One of the timestamps in one tables I work with is stored as a java epoch.  Here is a function I wrote to convert it to a timestamp.

This is done in DB2 on a iSeries so some you may need to edit it some.  In particular ant line that *SomeWord is probably a iSeries thing.

CREATE FUNCTION YFUALFA.TIMESTAMP_EPOCH ( 
 EPOCH BIGINT ) 
 RETURNS TIMESTAMP   
 LANGUAGE SQL 
 SPECIFIC YFUALFA.TIMESTAMP_EPOCH 
 DETERMINISTIC 
 READS SQL DATA 
 RETURNS NULL ON NULL INPUT 
 NO EXTERNAL ACTION 
 SET OPTION  ALWBLK = *ALLREAD , 
 ALWCPYDTA = *OPTIMIZE , 
 COMMIT = *NONE , 
 DECRESULT = (31, 31, 00) , 
 DFTRDBCOL = *NONE , 
 DYNDFTCOL = *NO , 
 DYNUSRPRF = *USER , 
 SRTSEQ = *HEX   
 RETURN TIMESTAMP ( '1970-01-01' , '00:00:00' ) + EPOCH SECONDS  ; 
  
COMMENT ON SPECIFIC FUNCTION YFUALFA.TIMESTAMP_EPOCH 
 IS 'Timestamp from a Java epoch' ;

Thursday, May 30, 2013

How to create a Hibernate UserType for a Boolean that really works

So I am working with a legacy database using JPA/Hibernate.  Our booleans are stored as a VARCHAR(5) with the values of either 'true' or 'false',  This does not lend its self to using the built in Hibernate type or either yes_no or true_false.

I tried using Hibernates org.hibernate.usertype.UserType interface to create a user type.  This almost worked.  I was able to successfully read and write data.  The problem was that if I had a query in which  I want to statically use true or false I had to singe quote the true or false.  See below for what did and did not work.

What I wanted

Select ss from StudentSupportSurvey ss where ss.stopNags = true 

What I had to do

Select ss from StudentSupportSurvey ss where ss.stopNags = 'true' 

UserType that worked

Notice that I did not implement UserType I instead extended AbstractSingleColumnStandardBasicType.  In my opinion it is probably always better to override one of the abstract classes found in org.hibernate.type then to implement UserType.

package org.yfu.util.hibernate;

import java.io.Serializable;

import org.hibernate.dialect.Dialect;
import org.hibernate.type.AbstractSingleColumnStandardBasicType;
import org.hibernate.type.DiscriminatorType;
import org.hibernate.type.PrimitiveType;
import org.hibernate.type.StringType;
import org.hibernate.type.descriptor.java.BooleanTypeDescriptor;
import org.hibernate.type.descriptor.sql.VarcharTypeDescriptor;

public class TrueFalseBooleanUserType extends AbstractSingleColumnStandardBasicType<Boolean>
 implements PrimitiveType<Boolean>, DiscriminatorType<Boolean>{

 private static final long serialVersionUID = -2794554001044861116L;
 
 public TrueFalseBooleanUserType() {
  super(VarcharTypeDescriptor.INSTANCE, BooleanTypeDescriptor.INSTANCE);
 }

 @Override
 public String getName() {
  return "yfu_boolean";
 }
 
 public Class getPrimitiveClass() {
  return boolean.class;
 }

 public Boolean stringToObject(String xml) throws Exception {
  return fromString( xml );
 }

 public Serializable getDefaultValue() {
  return Boolean.FALSE;
 }

 public String objectToSQLString(Boolean value, Dialect dialect) throws Exception {
  return StringType.INSTANCE.objectToSQLString( value.booleanValue() ? "true" : "false", dialect );
 }
}

This allowed me to right my query like this:
Select ss from StudentSupportSurvey ss where ss.stopNags = true 

Tuesday, April 30, 2013

JodaTime jadira.usertype.autoRegisterUserTypes in a persistence jar

So I have had no problem using UserType to have Joda Time objects in my JEE project when it was in a WAR.  I then took the war and made it into an EAR with all of the JPA classes in their own JAR.  The persistence.xml file was in this JAR.  When I started up the application in JBOSS 7.1.1 I got the following error.

Could not determine type for: org.jadira.usertype.dateandtime.joda.PersistentDateTime

This is what I did to fix it. In my pom.xml I made sure the Usertype.core depedency was there and most importanly I made sure that the manifest had it in the classpath.  You add the classpath to the manifest by adding addClasspath to the compiler plugin.   I also added jadira.usertype.autoRegisterUserTypes to the persistence.xml file. Here are some snippets:

 pom.xml

        <dependency>
            <groupId>org.jadira.usertype</groupId>
            <artifactId>usertype.core</artifactId>
        </dependency>
            <plugin>
                <artifactId>maven-compiler-plugin</artifactId>
                <configuration>
                    <source>1.7</source>
                    <target>1.7</target>
                    <archive>
                        <manifest>
                               <addClasspath>true</addClasspath>
                         </manifest>
                    </archive>               
                    
                    <compilerarguments>
                        <processor>org.hibernate.jpamodelgen.JPAMetaModelEntityProcessor</processor>
                    </compilerarguments>
                </configuration>
            </plugin>

persistence.xml

   <persistence-unit name="primary" transaction-type="JTA">
      <!-- If you are running in a production environment, add a managed 
         data source, the example data source is just for proofs of concept! -->
      <jta-data-source>java:jboss/datasources/myyfu</jta-data-source>
      <non-jta-data-source>java:jboss/datasources/myyfu</non-jta-data-source>
      <shared-cache-mode>ENABLE_SELECTIVE</shared-cache-mode>
      <properties>
         <!-- Properties for Hibernate -->
        <property name="hibernate.hbm2ddl.auto" value="validate" />
        <property name="hibernate.show_sql" value="${hibernate.show_sql}" />
        <property name="hibernate.dialect" value="org.hibernate.dialect.DB2400Dialect"/>
        <property name="hibernate.default_schema" value="YFUALFA"/>
        <property name="hibernate.cache.use_second_level_cache" value="true" />
        <property name="hibernate.cache.use_query_cache" value="true" />
        <property name="hibernate.default_batch_fetch_size" value="25"/>     
        <property name="org.hibernate.envers.track_entities_changed_in_revision" value="true"/>     
        <property name="jadira.usertype.autoRegisterUserTypes" value="true" />
     </properties>
   </persistence-unit>

Friday, October 12, 2012

CAS Single Sign On Server Seam 3 Security Integration

Where I work at we use the CAS Single Signon Server so that our users only have to sign into one of our Web applications. They are then signed into all of our applications. This makes integration between them very easy. For my newest application We decided to use JSF and Seam Security.

Holder for CAS Returned Information

The following class is used to hold the information returned in the CAS Assertion. I have pulled out the getters, setters, equals and toString.

package org.yfu.util.cas;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;

import javax.inject.Inject;

import org.apache.commons.lang.StringUtils;
import org.jasig.cas.client.validation.Assertion;
import org.jboss.solder.logging.Logger;
import org.picketlink.idm.api.User;

public class CASUserBean implements Serializable, User 
{
 
 private static final long serialVersionUID = 401263788421715826L;
 
 @Inject
 private Logger log;
 
 
 private static final String STUDENT = "student";
// private static final String HOST_FAMILY = "hostfamily";
// private static final String PARTNER = "partner";
 private static final String VOLUNTEER = "volunteer";
 private static final String STAFF = "staff";
 private static final String REWARDS = "Rewards";
 private static final String TELEPHONE_NUMBER = "telephoneNumber";
 private static final String DEPARTMENT = "department";
 private static final String MAIL = "mail";
 private static final String TITLE = "title";
 private static final String ELECTRONIC_SIGNATURE = "electronicSignature";
 private static final String USER_LEVEL = "userLevel";
 private static final String POSTAL_CODE = "postalCode";
 private static final String SECURITY_QUESTION_ANSWER = "securityQuestionAnswer";
 private static final String SECURITY_QUESTION = "securityQuestion";
 private static final String PFO = "pfo";
 private static final String DISTINGUISHED_NAME = "distinguishedName";
 private static final String USER_PRINCIPAL_NAME = "userPrincipalName";
 private static final String NAME = "Name";


 private Integer pfoId;
 private String username;
 private String name;
 private List<String> groups = new ArrayList<String>();;
 private String email;
 private String securityQuestion;
 private String securityQuestionAnswer;
 private String postalCode;
 private String electronicSignature;
 private String title;
 private String studentID;
 private String department;
 private String telephone;
 private String userLevel;
 private Date validUntilDate; 
 private Date validFromDate;
 private String distinguishedName;
 private boolean loggedIn;
 private boolean staff;
 private boolean volunteer;
 
 
 public CASUserBean() {

 }
 
 public void init(Assertion assertion) {
  if (assertion != null && assertion.getPrincipal() != null) {
   this.validFromDate = assertion.getValidFromDate(); 
   this.validUntilDate = assertion.getValidUntilDate();
   Map<String, Object> attribs = assertion.getPrincipal().getAttributes();
   this.department = (String) attribs.get(DEPARTMENT);
   this.distinguishedName = (String) attribs.get(DISTINGUISHED_NAME);
   this.electronicSignature = (String) attribs.get(ELECTRONIC_SIGNATURE);
   this.email = (String) attribs.get(MAIL);
   this.name = (String) attribs.get(NAME);
   this.postalCode = (String) attribs.get(POSTAL_CODE);
   this.securityQuestion = (String) attribs.get(SECURITY_QUESTION);
   this.securityQuestionAnswer = (String) attribs.get(SECURITY_QUESTION_ANSWER);
   this.studentID = (String) attribs.get(STUDENT);
   this.telephone = (String) attribs.get(TELEPHONE_NUMBER);
   this.title = (String) attribs.get(TITLE);
   this.userLevel = (String) attribs.get(USER_LEVEL);
   this.username = (String) attribs.get(USER_PRINCIPAL_NAME);
   this.setLoggedIn(true);
   
   String value = (String) attribs.get(PFO);
   
   if (org.apache.commons.lang.StringUtils.isNotBlank(value)
     && org.apache.commons.lang.StringUtils.isNumeric(value)) {
    this.pfoId = Integer.valueOf(value);
   }
   
      
   groups = new ArrayList<String>();
   Object ldapGroups = attribs.get("group");
   
   if (ldapGroups instanceof List) {
    List<?> list = (List<?>) ldapGroups;
       for (Object obj : list ) {
        String group = (String) obj;
        addRole(group);
    }
   } else {
    addRole((String) ldapGroups);
   }
   
      
      value =  getDistinguishedName();
      
      if (StringUtils.contains(value, "DC=YFUUSA,DC=Local")) {
       groups.add(STAFF);
      }
      
      setStaff(getGroups().contains(STAFF));
      setVolunteer(getGroups().contains(VOLUNTEER));
  }
 }

 private void addRole(String group) {
  log.trace(group);
  group = StringUtils.substringAfter(group, "CN=");
  log.trace(group);
  group = StringUtils.substringBefore(group, ",");
  log.trace(group);
  if (StringUtils.isNotBlank(group)) {
   groups.add(group);
  }
 }

 @Override
 public String getKey() {
  return getDistinguishedName();
 }

 @Override
 public String getId() {
  return "" + getPfoId();
 }
}

Producer For CASUserBean

Nothing much interesting here.  Just a simple producer.  You could get away with out this I have it since I started not using Seam Security.

package org.yfu.util.cas;

import javax.enterprise.context.RequestScoped;
import javax.enterprise.context.SessionScoped;
import javax.enterprise.inject.Alternative;
import javax.enterprise.inject.New;
import javax.enterprise.inject.Produces;
import javax.inject.Inject;
import javax.inject.Named;
import javax.servlet.http.HttpSession;

import org.jasig.cas.client.util.AbstractCasFilter;
import org.jasig.cas.client.validation.Assertion;
import org.jboss.solder.servlet.http.HttpSessionStatus;

@RequestScoped @Alternative 
public class CASUserProducer {

 
 @Inject private HttpSessionStatus sessionStatus;
 
 public CASUserProducer() {
  
 }
 
 @Produces
 @Named("casUser")
 @SessionScoped
 public CASUserBean getCasUser(@New CASUserBean user) {
  CASUserBean ret = user;
  
  ret.setName("Not Logged in");
  
  if (sessionStatus.isActive()) {
   HttpSession session = sessionStatus.get();
   Assertion assertion = (Assertion) session.getAttribute(AbstractCasFilter.CONST_CAS_ASSERTION);
   if (assertion != null && assertion.getPrincipal() != null) {
    user.init(assertion);
    ret = user;
   }
  } 
  return ret;
 }

}

Seam Security Authenticator

The need this little class so that we can tell Seam Security we are logged in.  We also set the CASUserBean as our User.
package org.yfu.util.cas;

import javax.inject.Inject;
import javax.inject.Named;

import org.jboss.seam.security.BaseAuthenticator;
import org.jboss.seam.security.Identity;

public class CASSeamAuthenticator extends BaseAuthenticator
{

 
 @Inject  @Named("casUser")  private CASUserBean casUser;
 
 public CASSeamAuthenticator() {
 }

 @Override
 public void authenticate() {
  if (casUser != null && casUser.isLoggedIn()) {
   setStatus(AuthenticationStatus.SUCCESS);
   setUser(casUser);   
  }  

 }

 @Override
 public void postAuthenticate() {

 }


}


A Servlet Filter

We now create a Servlet filter that will be placed after our CAS Servlet Filters.  This is where we actually do the login (see line 38).
package org.jasig.cas.client.seam3.authentication;

import java.io.IOException;

import javax.inject.Inject;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import org.jasig.cas.client.util.AbstractCasFilter;
import org.jasig.cas.client.validation.Assertion;
import org.jboss.seam.security.Identity;
import org.yfu.util.cas.CASUserBean;


public class Seam3SecurityAuthenticationFilter implements Filter {


 @Inject private Identity identity;
 
 
 @Override
 public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse,
   FilterChain chain) throws IOException, ServletException {

        final HttpServletRequest request = (HttpServletRequest) servletRequest;
        final HttpServletResponse response = (HttpServletResponse) servletResponse;
        final HttpSession session = request.getSession(false);
        final Assertion assertion = session != null ? (Assertion) session.getAttribute(AbstractCasFilter.CONST_CAS_ASSERTION) : null;

        if (!identity.isLoggedIn() && assertion != null) {
         identity.login();  // this is alway successful
         
         CASUserBean user = (CASUserBean) identity.getUser();
         
         // Now we will add LDAP Groups as Groups with a group type of group.  
         
         for (String group : user.getGroups()) {
    identity.addGroup(group, "group");
   }
         
         
         
        }
         
        
        chain.doFilter(request, response);
  
 }


 @Override
 public void init(FilterConfig filterConfig) throws ServletException {
  
 }


 @Override
 public void destroy() {
  
 }

 
}

Include the filter in the web.xml

I included the CAS filters so that you can see them in order. The order of the filter mappings is vitally important.

 
  CASWebAuthenticationFilter
  org.jasig.cas.client.jboss.authentication.WebAuthenticationFilter7
  
   casServerLoginUrl
   https://login.yfu.org/cas/login
  
  
   serverName
   ${cas.serverName}
  
 
 
  CASAuthenticationFilter
  org.jasig.cas.client.authentication.AuthenticationFilter
  
   casServerLoginUrl
   https://login.yfu.org/cas/login
  
  
   serverName
   ${cas.serverName}
  
 
 
  CASSeam3SecurityFilter
  org.jasig.cas.client.seam3.authentication.Seam3SecurityAuthenticationFilter
 
 
 
 
  CASWebAuthenticationFilter
  /secured/*
 
 
  CASAuthenticationFilter
  /secured/*
 
 
  CASSeam3SecurityFilter
  /secured/*
 

Wednesday, September 26, 2012

jQuery Character Counter for Multiple Textareas

The problem I had was the user is displayed a form where there are multiple textareas that they had to type at least 140 characters in all the textareas.

Below is the jQuery code I wrote to do it:

table is the id of a table that that all the textareas are a descendent of
cntOut is the id of a span I stick the count into.

jQuery('#table').on("blur keyup", "textarea", function(e) { var cnt = 0; jQuery("textarea").each( function(o) { cnt += this.textLength; }); jQuery(PrimeFaces.escapeClientId('#cntOut')).text(cnt); });

Thursday, May 17, 2012

DB2 Converting YYYYMMDD to timestamp

So my company has a iSeries server that includes a legacy application that stored dates as YYYYMMDD numeric(8,0). Time are stored as HHMM numeric(4,0). I have finally been able to create a function that take these 2 types of columns and return a timestamp.

 On of the cool things about the iSeries is that a data file that is written to my a legacy RPG program can be munipultated using SQL. From a client like JDBC or some DB2 client those file look just like a table. This is why the legacy applications did not store the date in a TIMESTAMP column. below is the function.

CREATE FUNCTION COMMON.TIMESTAMP_FROM_YFU (
YFUDATE NUMERIC(8, 0) ,
YFUTIME NUMERIC(4, 0) )
RETURNS TIMESTAMP  
LANGUAGE SQL
SPECIFIC COMMON.TIMESTAMP_FROM_YFU
DETERMINISTIC
CONTAINS SQL
RETURNS NULL ON NULL INPUT
NO EXTERNAL ACTION
SET OPTION  ALWBLK = *ALLREAD ,
ALWCPYDTA = *OPTIMIZE ,
COMMIT = *NONE ,
DECRESULT = (31, 31, 00) ,
DFTRDBCOL = *NONE ,
DYNDFTCOL = *NO ,
DYNUSRPRF = *USER ,
SRTSEQ = *HEX  
RETURN TIMESTAMP_FORMAT ( VARCHAR ( YFUDATE ) || DIGITS ( YFUTIME ) , 'YYYYMMDDHH24MI' )  ;
 
COMMENT ON SPECIFIC FUNCTION COMMON.TIMESTAMP_FROM_YFU
IS 'Timestamp from YFU Date and time' ;

Monday, May 14, 2012

Death to a Deadlock

One of the systems I have been working on has has had a deadlock that happens intermittently for the last 6 years.  Well today I finally found it.  We have a thread that runs in our application that times how long a web request takes.  If the request takes more then 30 minuets it assumes a deadlock and kills the application.  The thread also send an email to the programmers.  Below is the code I inserted in the monitoring thread code that allowed me to find the deadlock.



public static StringBuffer getDeadTraces(StringBuffer errorStringBuff) {
        StringBuffer deadtraces = new StringBuffer();
	try {
	    long[] ids = ManagementFactory.getThreadMXBean().findDeadlockedThreads();
	    if(null != ids && ids.length > 0) {
	         Map map = Thread.getAllStackTraces();
		 Set set = map.entrySet();
		 for (long id : ids) {
		    for (Entry entry : set) {
			 Thread thread = entry.getKey();
			if (thread.getId() == id) {
				deadtraces.append("\n===================  ");
				deadtraces.append(thread.getName());
				StringBufferUtils.append(deadtraces, "  ===================","\n");
							
				for (StackTraceElement el : entry.getValue()) {
					StringBufferUtils.append(deadtraces, el.toString(),"\n");                    						
				}												
			}
		    }				 
	         }
	    }
	} catch (Exception e) {
		errorStringBuff.append("Error trying to create a snapshot: " + 
		e.getMessage() + org.apache.commons.lang.exception.ExceptionUtils.getFullStackTrace(e));
	}
	return deadtraces;
}


Friday, April 20, 2012

FindBugs

I just found the FindBugs project.  It is a great way of finding possible bugs in Java programs.  I spend some of my time taking care of a cranky old WebObjects + Java website.  I run the program against its code base and it found 368 possible errors.   Some were the relatively benign "Repeated conditional test" while others where the more serious "Incorrect lazy initialization and update of static field ".

Friday, October 14, 2011

CAS - Central Authentication Service

I've been working on getting a Central Authentication Service (CAS) server up.  This server allows all your web applications to have Single Sign On (SSO).  The service itself can run on any JSP container.  We are using Tomcat.  Each web application needs to be secured using a CAS client.  If you are using JEE or JSP CAS comes with some nice filters thatmake the sucuring pretty much invisible to the application.  As we use WebObjects and PHP we need to do some of our own plumbing.
 

Wednesday, August 17, 2011

YUM, Ant and Optional Tasks

So I have a program that's ant tasks works fine on my Mac but when I ran the task on a Linux box I got java.lang.ClassNotFoundException: org.apache.tools.ant.taskdefs.optional.TraXLiaison.  Well it turns out that YUM has split Apache Ant into a bunch of different packages.  In this case I needed to run the following command.


yum install ant-trax.noarch


Wednesday, August 3, 2011

DB2Plugin Added to Wonder

The DB2 database plugin for WebObjects that I wrote has been added to the Wonder Framework.  The Plugin supports both mainstream DB2 and DB2 for iSeries.  The biggest pain for using the plugin is getting the DB2 jars.  Check the README files for help on that.

Friday, July 22, 2011

Eclipse, JBoss and Javaee6 Maven Archtype

I created a new JBoss Java EE 6 project using the jboss-javaee6-webapp archtype.  I had to problems.  It had a  Missing artifact org.apache.xalan:xalan:jar:2.7.1-1.jbossorg:provided error which I fixed by editing the pom.xml file. Here is the change

     <dependency>
         <groupId>org.jboss.spec</groupId>
         <artifactId>jboss-javaee-web-6.0</artifactId>
         <version>2.0.0.Final</version>
         <type>pom</type>
         <scope>provided</scope>
         <exclusions>
            <exclusion>
               <groupId>org.apache.xalan</groupId>
               <artifactId>xalan</artifactId>
            </exclusion>
         </exclusions>
        
      </dependency>
      <dependency>
          <groupId>xalan</groupId>
          <artifactId>xalan</artifactId>
          <version>2.7.1</version>
    </dependency>

By excluding the problem dependency and adding in the generic dependency for xlan it built fine.

The harder problem was to get Eclipse to properly run the application on my JBoss server.  I am using Eclipse Indigo and  I went back and forth with m2eclipse and the eclipse project m2e.  Neither one seemed to do the trick.

In the end I used the mvn -Dwtpversion=2.0 eclipse:eclipse from the command line