November 20, 2018

Setting Global HTTP Session Timeout in JBoss EAP 6 and 7

JBoss EAP 6.x

Edit standalone.xml.


<subsystem xmlns="urn:jboss:domain:web:2.2" default-virtual-server="default-host" native="false" default-session-timeout="15">
...
</subsystem>

JBoss EAP 7.x

Edit standalone.xml.


<subsystem xmlns="urn:jboss:domain:undertow:4.0">
...
    <servlet-container name="default" default-session-timeout="15">
...
    </servlet-container>
...
</subsystem>

Note

You can set this in WEB-INF/web.xml also, but this is better to set globally.

Set HttpOnly and secure for Cookies in JBoss EAP 6 and 7

What is Cookie HttpOnly and secure?

Example

Set-Cookie: a=b; HttpOnly; SameSite=strict; secure

HttpOnly = No JavaScript

SameSite = no cross-origin cookie sharing

secure = SSL only

SameSite is not yet supported in all browser, see https://caniuse.com/#feat=same-site-cookie-attribute

JBoss EAP 6.x

Not supported to set globally. Best effort is deploy Servlet 3.0 web-fragment.xml and deploy overlay which is messy.

Next best in local application WEB-INF/web.xml.


<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
    version="3.0">
...
    <session-config>
        <!-- Session timeout after X MINUTES after no user interaction. -->
        <session-timeout>15</session-timeout>
        <cookie-config>
            <http-only>true</http-only>
            <secure>true</secure>
        </cookie-config>
        <tracking-mode>COOKIE</tracking-mode>
    </session-config>
</web-app>

JBoss EAP 7.x

Edit standalone.xml


<subsystem xmlns="urn:jboss:domain:undertow:4.0">
...
    <servlet-container name="default">
...
        <session-cookie http-only="true" secure="true" />
    </servlet-container>
...
</subsystem>

How to Enable RequestDump in JBoss EAP 6 and 7

What is RequestDump?

It is a great debugging tool, that prints HTTP request and response in jboss server.log.

JBoss EAP EAP 6.1.0 or later

Edit standalone.xml.


<subsystem xmlns="urn:jboss:domain:web:2.2" default-virtual-server="default-host" native="false">
    ...
    <virtual-server name="default-host" enable-welcome-root="true">
        ...
    </virtual-server>
    <valve name="RequestDumperValve" module="org.jboss.as.web" class-name="org.apache.catalina.valves.RequestDumperValve"/>
</subsystem>

JBoss EAP EAP 7.x

Edit standalone.xml.


<subsystem xmlns="urn:jboss:domain:undertow:4.0">
    ...
    <server name="default-server">
        ...
    </server>
    ...
    <filters>
        ...
        <expression-filter name="requestDumperExpression" expression="dump-request"/>
    </filters>
</subsystem>

November 17, 2018

Spring Security

What is it?

A security framework, that competes with a framework that are built in Java EE and theirs servers. And is a mandatory requirement when running Spring Boot.

Prerequisite

  • Will use Spring Tools (STS) version 3 and not version 4, since latest version lacks the built in Tomcat (actually it is a modified Spring Tomcat, Pivotal TC Server).
  • Will use my previous blog example of Getting Started with Spring MVC .
  • Will use jetty maven plugin (org.eclipse.jetty:jetty-maven-plugin) to test and run the application via 'mvn jetty:run'.

Setup


<dependency>
    <groupId>org.springframework.security</groupId>
    <artifactId>spring-security-web</artifactId>
    <version>${springframework.version}</version>
</dependency>
<dependency>
    <groupId>org.springframework.security</groupId>
    <artifactId>spring-security-config</artifactId>
    <version>${springframework.version}</version>
</dependency>

Add to the src/main/webapp/WEB-INF/web.xml.


    <filter>
        <filter-name>springSecurityFilterChain</filter-name>
        <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>springSecurityFilterChain</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>

and /WEB-INF/spring/security-context.xml to your contextConfigLocation. The complete web.xml looks now with Spring MVC:


<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
    version="3.1">

    <filter>
        <filter-name>springSecurityFilterChain</filter-name>
        <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>springSecurityFilterChain</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>

    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>
    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>
            /WEB-INF/spring/application-context.xml
            /WEB-INF/spring/security-context.xml
        </param-value>
    </context-param>

    <servlet>
        <servlet-name>DispatcherServlet</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value></param-value>
        </init-param>
        <load-on-startup>1</load-on-startup>
    </servlet>
    <servlet-mapping>
        <servlet-name>DispatcherServlet</servlet-name>
        <url-pattern>/</url-pattern>
    </servlet-mapping>
</web-app>

And now an example /WEB-INF/spring/security-context.xml which protectes all HTTP with the role 'ROLE_USER' and in-memory user 'foo' with password 'changeit' and role 'ROLE_USER'.


<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:security="http://www.springframework.org/schema/security"
    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security.xsd">

    <security:http auto-config="true" use-expressions="false">
        <security:intercept-url pattern="/**" access="ROLE_USER" />
    </security:http>

    <security:authentication-manager>
        <security:authentication-provider>
            <security:password-encoder ref="passwordEncoder" />
            <security:user-service> 
                <security:user name="foo" password="changeit" authorities="ROLE_USER" /> 
            </security:user-service>
        </security:authentication-provider>
    </security:authentication-manager>

    <!-- java.lang.IllegalArgumentException: There is no PasswordEncoder mapped for 
        the id "null" -->
    <bean id="passwordEncoder"
        class="org.springframework.security.crypto.password.NoOpPasswordEncoder"
        factory-method="getInstance" />
</beans>

Architectual Overview

Authorization

Either via XML (or Java which is the requirement for Spring Boot).


<security:http auto-config="true" use-expressions="false">
    <security:intercept-url pattern="/**" access="ROLE_USER" />
</security:http>

What is important is that the rule with highest clearance must come first and then in decreased clearance. The reason for this is because the first rule that passes, will exit the process. Example of a misconfiguration.


<security:http auto-config="true" use-expressions="false">
    <security:intercept-url pattern="/**" access="ROLE_ANONYMOUS" />
    <security:intercept-url pattern="/topsecret/*" access="ROLE_TOP_SECRET" />
</security:http>

This configuration will lead to that everyone will be granted access to '/topsecret/*', since the first rule will be successfull and will overlay any further more restricted authorization rules.

Another way to enforce authoriation is via class or method annotation @org.springframework.security.access.annotation.Secured. Example:


@Secured({ "ROLE_USER" })
public void create(Contact contact) {...}

Authentication

Basic

/WEB-INF/spring/security-context.xml


    <security:http auto-config="true" use-expressions="false">
        <security:http-basic />
        ...
    </security:http>

Form

/WEB-INF/spring/security-context.xml


    <security:http auto-config="true" use-expressions="false">
        <security:form-login login-page="/login"
            login-processing-url="/login" default-target-url="/"
            always-use-default-target="true"
            authentication-failure-url="/login?error=true" />
        ...
    </security:http>

View in JSP.


<form action=${loginVar} method="POST">
Username: <input type="text" name="username" /></br>
Password: <input type="password" name="password" /></br>
<input type="submit" value="Login" />
</form>

Logout

View in JSP.


<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
...
<a href="<c:url value="/logout" />">Logout</a>
...

/WEB-INF/spring/security-context.xml


    <security:http auto-config="true" use-expressions="false">
        ...
        <security:logout logout-success-url="/login?logout=true"/>
        ...
    </security:http>

JDBC Module

Add maven dependency


        <dependency>
            <groupId>org.springframework.data</groupId>
            <artifactId>spring-data-jpa</artifactId>
            <version>2.1.1.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>com.h2database</groupId>
            <artifactId>h2</artifactId>
            <version>1.4.185</version>
        </dependency>

WEB-INF/spring/application-context.xml


<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:context="http://www.springframework.org/schema/context"
    xmlns:mvc="http://www.springframework.org/schema/mvc"
    xmlns:jdbc="http://www.springframework.org/schema/jdbc"
    xmlns:jpa="http://www.springframework.org/schema/data/jpa"
    xmlns:tx="http://www.springframework.org/schema/tx"
    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
        http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd
        http://www.springframework.org/schema/jdbc http://www.springframework.org/schema/jdbc/spring-jdbc.xsd
        http://www.springframework.org/schema/data/jpa http://www.springframework.org/schema/data/jpa/spring-jpa.xsd
        http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd">

    <tx:annotation-driven />

    <jdbc:embedded-database id="datasource" type="H2">
        <jdbc:script location="classpath:initdb.sql" />
    </jdbc:embedded-database>

    ...
</beans>

src/main/resources/initdb.sql


drop table users if exists;
drop table authorities if exists;

create table users(
    username varchar_ignorecase(50) not null primary key,
    password varchar_ignorecase(50) not null,
    enabled boolean not null
);

create table authorities (
    username varchar_ignorecase(50) not null,
    authority varchar_ignorecase(50) not null,
    constraint fk_authorities_users foreign key(username) references users(username)
);
create unique index ix_auth_username on authorities (username,authority);

insert into users(username, password, enabled) values ('foodb', 'changeit', true);
insert into authorities(username, authority) values ('foodb', 'ROLE_USER');

src/main/webapp/WEB-INF/spring/security-context.xml


    <security:authentication-manager>
        <security:authentication-provider>
            <security:password-encoder ref="passwordEncoder" />
            <security:jdbc-user-service data-source-ref="datasource" />
        </security:authentication-provider>
    </security:authentication-manager>

Advanced JDBC Module - Groups

src/main/webapp/WEB-INF/spring/security-context.xml


    <security:authentication-manager>
        <security:authentication-provider>
            <security:password-encoder ref="passwordEncoder" />
            <security:jdbc-user-service data-source-ref="datasource"
                group-authorities-by-username-query="select g.id, g.group_name, ga.authority
                    from groups g, group_members gm, group_authorities ga
                    where gm.username = ? and g.id = ga.group_id and g.id = gm.group_id" />
        </security:authentication-provider>
    </security:authentication-manager>

src/main/resources/initdb.sql add the Group Authorities tables


create table groups (
    id bigint generated by default as identity(start with 0) primary key,
    group_name varchar_ignorecase(50) not null
);

create table group_authorities (
    group_id bigint not null,
    authority varchar(50) not null,
    constraint fk_group_authorities_group foreign key(group_id) references groups(id)
);

create table group_members (
    id bigint generated by default as identity(start with 0) primary key,
    username varchar(50) not null,
    group_id bigint not null,
    constraint fk_group_members_group foreign key(group_id) references groups(id)
);

And remove the 'insert into authorities' and instead insert into group authorities tables.


insert into users(username, password, enabled) values ('foodb', 'changeit', true);
--insert into authorities(username, authority) values ('foodb', 'ROLE_USER');
insert into groups(id, group_name) values (1, 'Admin');
insert into group_authorities(group_id, authority) values (1, 'ROLE_USER');
insert into group_members(id, username, group_id) values (1, 'foodb', 1);

Hash Algorithm

https://docs.spring.io/spring-security/site/docs/current/api/org/springframework/security/crypto/password/PasswordEncoder.html

LDAP Module

Will use The Apache Directory, which is written in Java.

Download Apache DS. Download Archive zip/tar.gz.

Apache Directory Studio. Download Archive zip/tar.gz.

Unzip both zip/tar.gz to your desktop.


$ cd /home/magnuskkarlsson/bin/apacheds-2.0.0.AM25/bin
$ ./apacheds.sh start
Using ADS_HOME:    /home/magnuskkarlsson/bin/apacheds-2.0.0.AM25
Using JAVA_HOME:   

Starting ApacheDS instance 'default'...

Now start your 'ApacheDirectoryStudio'. Goto view 'LDAP Servers', click new and add ApacheDS 2.0.0 server. Then stop your apacheds server.


$ ./apacheds.sh stop

Return to studio and right click on you ApacheDS server and choose 'Create a Connection' and right click again and choose 'Run'.

Now we need to add a new partition for your database. Switch to LDAP Servers and double click on your local ldap, in the main space click Partitions and click Add.

After editing click Save. Then stop you local ldap and then start. After restarted double click on Connection and you will see your new partition.

Now we are going to import our users. Right click on Root DSE and choose Import and LDIF Import.

src/test/resources/spring-security-ldap.ldif


dn: dc=magnuskkarlsson,dc=se
objectclass: top
objectclass: domain
objectclass: extensibleObject
dc: magnuskkarlsson

dn: ou=groups,dc=magnuskkarlsson,dc=se
objectclass: top
objectclass: organizationalUnit
ou: groups

dn: ou=people,dc=magnuskkarlsson,dc=se
objectclass: top
objectclass: organizationalUnit
ou: people


dn: uid=ben,ou=people,dc=magnuskkarlsson,dc=se
objectclass: top
objectclass: person
objectclass: organizationalPerson
objectclass: inetOrgPerson
cn: Ben Alex
sn: Alex
uid: ben
userPassword: changeit

dn: uid=bob,ou=people,dc=magnuskkarlsson,dc=se
objectclass: top
objectclass: person
objectclass: organizationalPerson
objectclass: inetOrgPerson
cn: Bob Hamilton
sn: Hamilton
uid: bob
userPassword: changeit


dn: cn=user,ou=groups,dc=magnuskkarlsson,dc=se
objectclass: top
objectclass: groupOfUniqueNames
cn: user
uniqueMember: uid=ben,ou=people,dc=magnuskkarlsson,dc=se
uniqueMember: uid=bob,ou=people,dc=magnuskkarlsson,dc=se

dn: cn=admin,ou=groups,dc=magnuskkarlsson,dc=se
objectclass: top
objectclass: groupOfUniqueNames
cn: admin
uniqueMember: uid=ben,ou=people,dc=magnuskkarlsson,dc=se

Now configure Spring Security LDAP, but first we need to add maven dependency.


        <dependency>
            <groupId>org.springframework.security</groupId>
            <artifactId>spring-security-ldap</artifactId>
            <version>${springframework.version}</version>
        </dependency>

src/main/webapp/WEB-INF/spring/security-context-ldap.xml


<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:security="http://www.springframework.org/schema/security"
    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security.xsd">

    <security:http auto-config="true" use-expressions="false">
        <security:intercept-url pattern="/**" access="ROLE_USER" />
        <security:logout logout-success-url="/login" />
    </security:http>

    <security:authentication-manager>
        <security:ldap-authentication-provider server-ref="ldapServer" 
            user-dn-pattern="uid={0},ou=people" group-search-base="ou=groups">
        </security:ldap-authentication-provider>
    </security:authentication-manager>

    <security:ldap-server id="ldapServer" 
        url="ldap://localhost:10389/dc=magnuskkarlsson,dc=se" 
        manager-dn="uid=admin,ou=system" manager-password="secret" />
</beans>

Expression-Based Access Control/Spring Expression Language(SPEL)

First you need to declare SPEL bean then change 'use-expressions' to true. Then you can use your expression.

https://docs.spring.io/spring-security/site/docs/current/reference/htmlsingle/#el-access


    <bean class="org.springframework.security.web.access.expression.DefaultWebSecurityExpressionHandler" />

    <security:http auto-config="true" use-expressions="true">
        
        <security:intercept-url pattern="/**" access="hasRole('ROLE_USER') and hasIpAddress('192.168.1.0/24')" />
        ...
    </security:http>

Spring Security Taglib


        <dependency>
            <groupId>org.springframework.security</groupId>
            <artifactId>spring-security-taglibs</artifactId>
            <version>${springframework.version}</version>
        </dependency>

<%@ taglib prefix="sec" uri="http://www.springframework.org/security/tags" %>

https://docs.spring.io/spring-security/site/docs/current/reference/htmlsingle/#taglibs

Example in your JSP page.


<sec:authorize access="isAuthenticated()">
    Welcome 
    <sec:authentication property="principal.firstName"/> 
    <sec:authentication! property="principal.lastName"/>
</sec:authorize>

<sec:authorize access="hasRole('ROLE_ADMIN')">
    TOP SECRET
</sec:authorize>

Access Control List, ACL

The ACL is used to grant access to specific person and/or rule to specfic instances of a object.

Example. You have reports and some reports (db with primary key e.g. 1 and 3) should only be accessed by user (db primary key user e.g. 1, 5). That can you enforce with ACL.

Or specific reports should only be granted read access, that can also be enforced with ACL.

The downside with ACL is management of this finegrained access control.

https://docs.spring.io/spring-security/site/docs/current/reference/htmlsingle/#dbschema-acl

https://www.baeldung.com/spring-security-acl

CSRF

Use spring security form taglib


<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form"%>

<form:form ...>
</form>

Eitherwise you need to manually add it.


<%@ taglib prefix="sec" uri="http://www.springframework.org/security/tags" %>

<form ...>
    <sec:csrfInput />
</form>

Java Configuration Part

So far I have configured Spring Security through XML, but today in the spring community is moving to writing java code instead. My opinion is that XML is more concisely and more easy to overview, but XML has a bad reputation in the spring community.

Start class.


package se.magnuskkarlsson.example.springmvc;

import org.springframework.security.web.context.AbstractSecurityWebApplicationInitializer;

public class SecurityWebApplicationInitializer extends AbstractSecurityWebApplicationInitializer {

    public SecurityWebApplicationInitializer() {
        super(SecurityConfig.class);
    }
}

Then the actual authentication and authorization code.


package se.magnuskkarlsson.example.springmvc;

import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.ImportResource;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;

@Configuration
@EnableWebSecurity
@ImportResource("/WEB-INF/spring/application-context.xml")
@ComponentScan("se.magnuskkarlsson.example")
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.inMemoryAuthentication().withUser("foojava").password("changeit").roles("USER");
    }
}

November 13, 2018

Getting Started with Spring MVC

The OLD XML Configuration

pom.xml. The jstl and servlet-api is only need if you use JSTL in your JSP pages.


<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">

    <modelVersion>4.0.0</modelVersion>
    <groupId>se.magnuskkarlsson.examples</groupId>
    <artifactId>example-springmvc-xml</artifactId>
    <version>1.0.0-SNAPSHOT</version>
    <packaging>war</packaging>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.build.outputEncoding>UTF-8</project.build.outputEncoding>
        <maven.compiler.source>1.8</maven.compiler.source>
        <maven.compiler.target>1.8</maven.compiler.target>
        <failOnMissingWebXml>false</failOnMissingWebXml>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-webmvc</artifactId>
            <version>5.1.2.RELEASE</version>
        </dependency>

        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>jstl</artifactId>
            <version>1.2</version>
        </dependency>
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>javax.servlet-api</artifactId>
            <version>3.1.0</version>
            <scope>provided</scope>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <!-- embedded Jetty server, for testing -->
            <plugin>
                <groupId>org.eclipse.jetty</groupId>
                <artifactId>jetty-maven-plugin</artifactId>
                <version>9.2.11.v20150529</version>
                <configuration>
                    <scanIntervalSeconds>10</scanIntervalSeconds>
                    <webApp>
                        <contextPath>/</contextPath>
                    </webApp>
                </configuration>
            </plugin>
        </plugins>
    </build>
</project>

web.xml. The old school, but is good to know, since there are several old references to the XML way.


<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
    version="3.1">

    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>
    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>/WEB-INF/spring/application-context.xml</param-value>
    </context-param>

    <servlet>
        <servlet-name>DispatcherServlet</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value></param-value>
        </init-param>
        <load-on-startup>1</load-on-startup>
    </servlet>
    <servlet-mapping>
        <servlet-name>DispatcherServlet</servlet-name>
        <url-pattern>/</url-pattern>
    </servlet-mapping>
</web-app>

/WEB-INF/spring/application-context.xmlIn Spring you can split the Spring XML configuration into several files, but I tend to think that using several configuration files, will only make you wander lost in configuration, so I prefer one configuration file.


<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:context="http://www.springframework.org/schema/context"
    xmlns:mvc="http://www.springframework.org/schema/mvc"
    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
        http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd">

    <context:component-scan base-package="se.magnuskkarlsson.example.springmvc.controller" />

    <mvc:annotation-driven />

    <bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="prefix" value="/WEB-INF/view/" />
        <property name="suffix" value=".jsp" />
    </bean>
</beans>

Now the actual "app". Spring MVC design is much like Struts with one Servlet that dispatch request. HelloController


package se.magnuskkarlsson.example.springmvc.controller;

import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;

@Controller
public class HelloController {

    @RequestMapping(value = "/hello", method = RequestMethod.GET)
    public String hello(@RequestParam(value = "name", required = false, defaultValue = "World") String name,
            Model model) {

        model.addAttribute("name", name);
        return "hello";
    }
}

And your app view - WEB-INF/view/hello.jsp


<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<%@ taglib prefix="spring" uri="http://www.springframework.org/tags"%>
<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Hello Spring MVC</title>
</head>
<body>
    <h2>Hello Java ${name}!</h2>
</body>
</html>

And finally lets test it by running 'mvn jetty:run' and open http://localhost:8080/hello?name=foo.


$ mvn clean install; mvn jetty:run

The NEW Java Configuration

Now we delete web.xml and /WEB-INF/spring/application-context.xml. And manually write code that do the same thing.


package se.magnuskkarlsson.example.springmvc;

import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.ServletRegistration;

import org.springframework.web.WebApplicationInitializer;
import org.springframework.web.context.ContextLoaderListener;
import org.springframework.web.context.support.AnnotationConfigWebApplicationContext;
import org.springframework.web.context.support.GenericWebApplicationContext;
import org.springframework.web.servlet.DispatcherServlet;

public class MainWebAppInitializer implements WebApplicationInitializer {

    @Override
    public void onStartup(ServletContext container) throws ServletException {
        // Create the 'root' Spring application context
        AnnotationConfigWebApplicationContext rootContext = new AnnotationConfigWebApplicationContext();
        rootContext.scan("se.magnuskkarlsson");

        // Manage the lifecycle of the root application context
        container.addListener(new ContextLoaderListener(rootContext));

        // Register and map the dispatcher servlet
        ServletRegistration.Dynamic dispatcher = container.addServlet("dispatcher",
                new DispatcherServlet(new GenericWebApplicationContext()));
        dispatcher.setLoadOnStartup(1);
        dispatcher.addMapping("/");
    }
}

package se.magnuskkarlsson.example.springmvc;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.ViewResolver;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import org.springframework.web.servlet.view.InternalResourceViewResolver;

@EnableWebMvc
@Configuration
@ComponentScan(basePackages = { "se.magnuskkarlsson.example.springmvc.controller" })
public class AppConfig implements WebMvcConfigurer {

    @Bean
    public ViewResolver viewResolver() {
        InternalResourceViewResolver bean = new InternalResourceViewResolver();
        bean.setPrefix("/WEB-INF/view/");
        bean.setSuffix(".jsp");
        return bean;
    }
}

November 11, 2018

TestNG

Comparison with JUnit

TestNG is a direct competitor with JUnit. But that may change with JUnit 5.

The main advantage of TestNG compared with JUnit 4, is that TestNG has build in support of Data Provider and Parallel support.

Below follows a summary of feature in TestNG.

Setup

Maven


<dependency>
    <groupId>org.testng</groupId>
    <artifactId>testng</artifactId>
    <version>6.14.3</version>
    <scope>test</scope>
</dependency>

Eclipse

Open Eclipse and click on Help menu and Install New Software. Enter http://beust.com/eclipse

And then next and finish plugin installation.

TestNG Annotations


    @BeforeSuite
    @AfterSuite

    @BeforeTest
    @AfterTest

    @BeforeClass
    @AfterClass

    @BeforeMethod
    @AfterMethod

    @Test

    // order, but each test method should be independent
    @Test(priority=0)

Grouping Related Test Methods


    // group test method, so they are executed logical together
    @Test(groups = "cars")

Used for test suite, annotate with attribute group and call group in test suite xml.

TestNG Assert


    org.testng.Assert
        assertTrue
        assertFalse
        fail
        assertEquals
        assertNotNull
        assertNull
        assertSame
        assertNotSame

Running a Test Suite


<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd" >
<suite name="tests">
    <test name="backend">
        <classes>
            <class name="se.magnuskkarksson.testng.SimpleTest" />
        </classes>
    </test>
</suite>

To run, right click on xml file and choose TestNG Suite

See also for more example of test suite. http://websystique.com/java/testing/testng-suites-example/

For Maven Surefire Plugin see http://maven.apache.org/surefire/maven-surefire-plugin/examples/testng.html

Dependent Test Methods


@Test(dependsOnMethods = {"test1"})
public void test1() throws Exception { }

@Test(dependsOnMethods = {"test2"})
public void test2() throws Exception { }

Disable and Timeout Test


@Test(enabled = false)
public void testEnabled() throws Exception { }

// The maximum number of milliseconds
@Test(timeOut = 1000)
public void testTimeConstraint() throws Exception { }

Providing Test Data from XML file


<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd" >
<suite name="tests">
    <test name="backend">
        <parameter name="param1" value="value1" />
        <parameter name="param2" value="value2" />
        <parameter name="param3" value="value3" />
        <classes>
            <class name="se.magnuskkarksson.testng.SimpleTest" />
        </classes>
    </test>
</suite>

@BeforeClass
@Parameters({ "param1", "param2" })
public void beforeClass(String param1, String param2) throws Exception { }

@Test
@Parameters({ "param1" })
public void test(String param1) throws Exception { }

Running Tests in Parallel


<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd" >
<suite name="tests" parallel="tests" thread-count="2">
 
    <test name="front-end">
        <packages>
            <package name="se.magnuskkarlsson.testng.frontend.*" />
        </packages>
    </test>
    <test name="back-end">
        <packages>
            <package name="se.magnuskkarlsson.testng.backend.*" />
        </packages>
    </test>
</suite>

Data Providers


package se.magnuskkarksson.testng;

import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;

public class DataProviderTest {

    @Test(dataProvider = "testData")
    public void test(String param1, String param2) throws Exception {
        System.out.println("param1: " + param1 + ", param2: " + param2);
    }

    @DataProvider(name = "testData")
    public Object[][] getTestData() {
        return new Object[][] { //
                { "foo1", "bar1" }, //
                { "foo2", "bar2" } //
        };
    }
}

To reuse testdata move data provider to seperate class.


package se.magnuskkarksson.testng;

import org.testng.annotations.DataProvider;

public class TestData {

    @DataProvider(name = "testData")
    public Object[][] getTestData() {
        return new Object[][] { //
                { "foo1", "bar1" }, //
                { "foo2", "bar2" } //
        };
    }
}

Then modify @Test annotation attribute


package se.magnuskkarksson.testng;

import org.testng.annotations.Test;

public class DataProviderTest {

    @Test(dataProvider = "testData", dataProviderClass = TestData.class)
    public void test(String param1, String param2) throws Exception {
        System.out.println("param1: " + param1 + ", param2: " + param2);
    }
}

TestNG Listeners


org.testng.ITestResult 
org.testng.IInvokedMethodListener
org.testng.ITestListener
org.testng.ISuiteListener

TestNG Reporter Logs and HTML Reports

To create HTML TestNG report add org.testng.Reporter#log() logging to your unit test file. E.g.


@Test
public void aFastTest() {
    Assert.assertTrue(true);
    Reporter.log("Logging.....");
}

Then create test suite xml file and run test suite. Then will a test-output directory be created with a HTML report in it.

TestNG Selenium

Install chrome web browser. On Fedora 28 'yum install google-chrome-stable'

Download chrome webdriver from selenium web page - https://www.seleniumhq.org/download/. Which links to https://chromedriver.storage.googleapis.com/index.html?path=2.43/.

Download zip file and unzip somewhere on disk.

Add selenium for java maven dependency.


<dependency>
    <groupId>org.seleniumhq.selenium</groupId>
    <artifactId>selenium-java</artifactId>
    <version>3.141.5</version>
    <scope>test</scope>
</dependency>

Write test unit test.


package se.magnuskkarksson.testng;

import org.openqa.selenium.WebDriver;
import org.testng.Assert;
import org.testng.annotations.AfterClass;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.Test;
import org.openqa.selenium.chrome.ChromeDriver;

public class SeleniumParallelTest {

    private String baseUrl;

    private WebDriver driver;

    @BeforeClass
    public void beforeClass() throws Exception {
        baseUrl = "https://www.google.com/";
        System.setProperty("webdriver.chrome.driver",
                "/home/magnuskkarlsson/bin/selenium/chromedriver_linux64/chromedriver");
        driver = new ChromeDriver();
        driver.get(baseUrl);
    }

    @AfterClass
    public void afterClass() throws Exception {
        driver.quit();
    }

    @Test
    public void test() throws Exception {
        String title = driver.getTitle();
        System.out.println("Title: " + title);
        Assert.assertEquals(title, "Google");
    }
}

November 2, 2018

Oracle Code One 2018 Keynote by Mark Reinhold Chief Architect

Entire Keynote

https://www.youtube.com/watch?v=RFF2SfPMfpk

Oracle JDK for Windows is Not Free Anymore

Oracle JDK for Windows is Not Free Anymore

Subscription
$ 25.00 per month per processer
$ 2.50 per month and user
https://www.oracle.com/java/java-se-subscription.html

Who is contributing to OpenJDK?

https://blogs.oracle.com/java-platform-group/building-jdk-11-together

Java Champions

https://github.com/aalmiray/java-champions

Packages Removed in Java 11

Before Java 11

After Java 11

Reference

  1. JEP 261: Module System (Jigsaw)
  2. JEP 320: Remove the Java EE and CORBA Modules

Removed in Java 9


java.util.jar.Pack200.Packer.addPropertyChangeListener(...)
java.util.jar.Pack200.Packer.removePropertyChangeListener(...)
java.util.jar.Pack200.Unpacker.addPropertyChangeListener(...)
java.util.jar.Pack200.Unpacker.removePropertyChangeListener(...)
java.util.logging.LogManager.addPropertyChangeListener(...)
java.util.logging.LogManager.removePropertyChangeListener(...)

Removed in Java 10


// Removed in Java 10
java.lang.Runtime.getLocalizedInputStream(...)
java.lang.Runtime.getLocalizedOutputStream(...)
java.lang.SecurityManager.classDepth(...)
java.lang.SecurityManager.classLoaderDepth()
java.lang.SecurityManager.currentClassLoader()
java.lang.SecurityManager.currentLoadedClass()
java.lang.SecurityManager.getInCheck()
java.lang.SecurityManager.inClass(...)
java.lang.SecurityManager.inClassLoader()

Removed in Java 11


// Removed in Java 11 (in addition to the Java EE & Corba modules)
java.lang.Runtime.runFinalizersOnExit(...)
java.lang.SecurityManager.checkAwtEventQueueAccess()
java.lang.SecurityManager.checkMemberAccess(...)
java.lang.SecurityManager.checkSystemClipboardAccess()
java.lang.SecurityManager.checkTopLevelWindow(...)
java.lang.System.runFinalizersOnExit(...)
javax.security.auth.Policy

To be Removed in a Future Release


java.io.FileInputStream.finalize()
java.io.FileOutputStream.finalize()
java.lang.Compiler
java.lang.Runtime.traceInstructions(...)
java.lang.Runtime.traceInstructions(...)
java.lang.Thread.countStackFrames()
java.security.acl
java.security.Certificate
java.security.Identity
java.security.IdentityScope
java.security.Signer
java.util.jar.Pack200
java.util.zip.Deflater.finalize()
java.util.zip.Inflater.finalize()
java.util.zip.ZipFile.finalize()
javax.management.remote.rmi.RMIConnectorServer.CREDENTIAL_TYPES

Solution of Removed Packages/Classes


compile 'com.sun.activation:javax.activation:1.2.0'
compile 'javax.transaction:javax.transaction-api:1.3'
compile 'com.sun.xml.bind:jaxb-impl:2.3.1'
compile 'com.sun.xml.ws:jaxws-ri:2.3.1'
compile 'javax.annotation:javax.annotation-api:1.3.2'

Check Deprecated packages


$ jdeps --jdk-internals app.jar

Oracle JDK LTS

Java 11 and next 17

Java 9 (91 JEPS)


102: Process API Updates
110: HTTP 2 Client
143: Improve Contended Locking
158: Unified JVM Logging
165: Compiler Control
193: Variable Handles
197: Segmented Code Cache
199: Smart Java Compilation, Phase Two
200: The Modular JDK
201: Modular Source Code
211: Elide Deprecation Warnings on Import Statements
212: Resolve Lint and Doclint Warnings
213: Milling Project Coin
214: Remove GC Combinations Deprecated in JDK 8
215: Tiered Attribution for javac
216: Process Import Statements Correctly
217: Annotations Pipeline 2.0
219: Datagram Transport Layer Security (DTLS)
220: Modular Run-Time Images
221: Simplified Doclet API
222: jshell: The Java Shell (Read-Eval-Print Loop)
223: New Version-String Scheme
224: HTML5 Javadoc
225: Javadoc Search
226: UTF-8 Property Files
227: Unicode 7.0
228: Add More Diagnostic Commands
229: Create PKCS12 Keystores by Default
231: Remove Launch-Time JRE Version Selection
232: Improve Secure Application Performance
233: Generate Run-Time Compiler Tests Automatically
235: Test Class-File Attributes Generated by javac
236: Parser API for Nashorn
237: Linux/AArch64 Port
238: Multi-Release JAR Files
240: Remove the JVM TI hprof Agent
241: Remove the jhat Tool
243: Java-Level JVM Compiler Interface
244: TLS Application-Layer Protocol Negotiation Extension
245: Validate JVM Command-Line Flag Arguments
246: Leverage CPU Instructions for GHASH and RSA
247: Compile for Older Platform Versions
248: Make G1 the Default Garbage Collector
249: OCSP Stapling for TLS
250: Store Interned Strings in CDS Archives
251: Multi-Resolution Images
252: Use CLDR Locale Data by Default
253: Prepare JavaFX UI Controls & CSS APIs for Modularization
254: Compact Strings
255: Merge Selected Xerces 2.11.0 Updates into JAXP
256: BeanInfo Annotations
257: Update JavaFX/Media to Newer Version of GStreamer
258: HarfBuzz Font-Layout Engine
259: Stack-Walking API
260: Encapsulate Most Internal APIs
261: Module System
262: TIFF Image I/O
263: HiDPI Graphics on Windows and Linux
264: Platform Logging API and Service
265: Marlin Graphics Renderer
266: More Concurrency Updates
267: Unicode 8.0
268: XML Catalogs
269: Convenience Factory Methods for Collections
270: Reserved Stack Areas for Critical Sections
271: Unified GC Logging
272: Platform-Specific Desktop Features
273: DRBG-Based SecureRandom Implementations
274: Enhanced Method Handles
275: Modular Java Application Packaging
276: Dynamic Linking of Language-Defined Object Models
277: Enhanced Deprecation
278: Additional Tests for Humongous Objects in G1
279: Improve Test-Failure Troubleshooting
280: Indify String Concatenation
281: HotSpot C++ Unit-Test Framework
282: jlink: The Java Linker
283: Enable GTK 3 on Linux
284: New HotSpot Build System
285: Spin-Wait Hints
287: SHA-3 Hash Algorithms
288: Disable SHA-1 Certificates
289: Deprecate the Applet API
290: Filter Incoming Serialization Data
291: Deprecate the Concurrent Mark Sweep (CMS) Garbage Collector
292: Implement Selected ECMAScript 6 Features in Nashorn
294: Linux/s390x Port
295: Ahead-of-Time Compilation
297: Unified arm32/arm64 Port
298: Remove Demos and Samples
299: Reorganize Documentation

https://openjdk.java.net/projects/jdk9/

Java 10 (12 JEPS)


JEP 286: Local-Variable Type Inference  https://openjdk.java.net/jeps/286
JEP 296: Consolidate the JDK Forest into a Single Repository    https://openjdk.java.net/jeps/296
JEP 304: Garbage Collector Interface    https://openjdk.java.net/jeps/304
JEP 307: Parallel Full GC for G1    https://openjdk.java.net/jeps/307
JEP 310: Application Class-Data Sharing https://openjdk.java.net/jeps/310
JEP 312: Thread-Local Handshakes    https://openjdk.java.net/jeps/312
JEP 313: Remove the Native-Header Generation Tool (javah)   https://openjdk.java.net/jeps/313
JEP 314: Additional Unicode Language-Tag Extensions https://openjdk.java.net/jeps/314
JEP 316: Heap Allocation on Alternative Memory Devices  https://openjdk.java.net/jeps/316
JEP 317: Experimental Java-Based JIT Compiler   https://openjdk.java.net/jeps/317
JEP 319: Root Certificates  https://openjdk.java.net/jeps/319
JEP 322: Time-Based Release Versioning  https://openjdk.java.net/jeps/322

https://openjdk.java.net/projects/jdk/10/

Java 11 (17 JEPS)


JEP 181: Nest-Based Access Control  https://openjdk.java.net/jeps/181
JEP 309: Dynamic Class-File Constants   https://openjdk.java.net/jeps/309
JEP 315: Improve Aarch64 Intrinsics https://openjdk.java.net/jeps/315
JEP 318: Epsilon: A No-Op Garbage Collector (Experimental)  https://openjdk.java.net/jeps/318
JEP 320: Remove the Java EE and CORBA Modules   https://openjdk.java.net/jeps/320
JEP 321: HTTP Client (Standard) https://openjdk.java.net/jeps/321
JEP 323: Local-Variable Syntax for Lambda Parameters    https://openjdk.java.net/jeps/323
JEP 324: Key Agreement with Curve25519 and Curve448 https://openjdk.java.net/jeps/324
JEP 327: Unicode 10 https://openjdk.java.net/jeps/327
JEP 328: Flight Recorder    https://openjdk.java.net/jeps/328
JEP 329: ChaCha20 and Poly1305 Cryptographic Algorithms https://openjdk.java.net/jeps/329
JEP 330: Launch Single-File Source-Code Programs    https://openjdk.java.net/jeps/330
JEP 331: Low-Overhead Heap Profiling    https://openjdk.java.net/jeps/331
JEP 332: Transport Layer Security (TLS) 1.3 https://openjdk.java.net/jeps/332
JEP 333: ZGC: A Scalable Low-Latency Garbage Collector (Experimental)   https://openjdk.java.net/jeps/333
JEP 335: Deprecate the Nashorn JavaScript Engine    https://openjdk.java.net/jeps/335
JEP 336: Deprecate the Pack200 Tools and API    https://openjdk.java.net/jeps/336

https://openjdk.java.net/projects/jdk/11/

Java 12- OpenJDK Projects


Amber: Right-sizing language cermenony   https://openjdk.java.net/projects/amber/
Loom: Continuations & Fibres    https://openjdk.java.net/projects/loom/
Panama: Foreign-function/data interface https://openjdk.java.net/projects/panama/  
Valhalla: Value types & specialized generics    https://openjdk.java.net/projects/valhalla/

https://openjdk.java.net/

November 1, 2018

JSF UI Components Overview

https://www.javatpoint.com/jsf-ui-components

https://www.tutorialspoint.com/jsf/index.htm

Security Testing in the Build Pipeline

PMD

PMD is a source code analyzer tool, but also have Copy/Paste Detector tool (CPD). https://maven.apache.org/plugins/maven-pmd-plugin/index.html


<project xmlns="http://maven.apache.org/POM/4.0.0"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    ...
    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-pmd-plugin</artifactId>
                <version>3.11.0</version>
                <executions>
                    <execution>
                        <goals>
                            <goal>check</goal>
                            <goal>cpd-check</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
            ...
        </plugins>
    </build>
</project>

Reference

  1. https://maven.apache.org/plugins/maven-pmd-plugin/plugin-info.html
  2. https://maven.apache.org/plugins/maven-pmd-plugin/examples/violationChecking.html
  3. https://docs.sonarqube.org/display/PLUG/Importing+SpotBugs%2C+FindSecBugs%2C+PMD%2C+Checkstyle+Issues+Reports

OWASP Dependency Check

Scan dependencies for known CVE against National Vulnerability Database, NVD.


<project xmlns="http://maven.apache.org/POM/4.0.0"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    ...
    <build>
        <plugins>
            <plugin>
                <groupId>org.owasp</groupId>
                <artifactId>dependency-check-maven</artifactId>
                <version>3.3.4</version>
                <executions>
                    <execution>
                        <goals>
                            <goal>check</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
            ...
        </plugins>
    </build>
</project>

Reference

  1. https://magnus-k-karlsson.blogspot.com/2018/10/owasp-dependency-check.html

SpotBugs

"SpotBugs is a program to find bugs in Java programs. It looks for instances of “bug patterns” — code instances that are likely to be errors." https://spotbugs.readthedocs.io/en/latest/introduction.html


<project xmlns="http://maven.apache.org/POM/4.0.0"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    ...
    <build>
        <plugins>
            <plugin>
                <groupId>com.github.spotbugs</groupId>
                <artifactId>spotbugs-maven-plugin</artifactId>
                <version>3.1.7</version>
                <configuration>
                    <effort>Max</effort>
                    <threshold>Low</threshold>
                    <failOnError>true</failOnError>
                    <includeFilterFile>${project.basedir}/spotbugs-security-include.xml</includeFilterFile>
                    <excludeFilterFile>${project.basedir}/spotbugs-security-exclude.xml</excludeFilterFile>
                    <plugins>
                        <plugin>
                            <groupId>com.h3xstream.findsecbugs</groupId>
                            <artifactId>findsecbugs-plugin</artifactId>
                            <version>LATEST</version> <!-- Auto-update to the latest stable -->
                        </plugin>
                    </plugins>
                </configuration>
                <executions>
                    <execution>
                        <goals>
                            <goal>check</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>
</project>

Reference

  1. https://github.com/find-sec-bugs/find-sec-bugs/wiki/Maven-configuration
  2. https://spotbugs.readthedocs.io/en/latest/maven.html
  3. https://find-sec-bugs.github.io/tutorials.htm

BDD

"The framework is essentially a set of Cucumber-JVM features that are pre-wired with Selenium/WebDriver, OWASP ZAP, SSLyze and Tennable's Nessus scanner." https://github.com/continuumsecurity/bdd-security


# Test App
$ wget https://github.com/continuumsecurity/RopeyTasks/raw/master/ropeytasks.jar
$ java -jar ropeytasks.jar

# Download framework and run extensive test
$ git clone https://github.com/continuumsecurity/bdd-security.git
$ ./gradlew
  1. https://github.com/continuumsecurity/bdd-security
  2. https://github.com/continuumsecurity/bdd-security/wiki/2-Getting-Started

October 28, 2018

JSF 2.0 (EE 6) Feature Red Hat JBoss EAP 6

Feature in JSF 2.0 (EE 6) GitHub JsfApplicationJboss.

Using JAAS in Tomcat Example

JAAS is part of the Java SE since Java 5, so choosing that API, when you want to deploy to only a web container, such as Tomcat or Jetty, is a good choice.

/META-INF/context.xml. See where best to put your configuration How to handle Configuration in Tomcat with Context


<?xml version="1.0" encoding="UTF-8"?>
<Context>
  <Realm className="org.apache.catalina.realm.JAASRealm" 
    appName="BytesLoungeLogin"
    userClassNames="com.byteslounge.jaas.UserPrincipal"
    roleClassNames="com.byteslounge.jaas.RolePrincipal" />
</Context>

$CATALINA_BASE/conf/jaas.config


BytesLoungeLogin {
    com.byteslounge.jaas.BytesLoungeLoginModule required debug=true;
};

And starting


JAVA_OPTS=$JAVA_OPTS "-Djava.security.auth.login.config==$CATALINA_BASE/conf/jaas.config"

JAAS authentication in Tomcat example

Scanning Your System with OpenSCAP

With SCAP and a good policy you can centrally scan your system and verify that they are properly secured and get a nice automatically report at the end.

Resource

Java Smart Card APDU Commands

Almost all smart card are Java Smart Card based. You can manage smart card via the Java Smart Card SDK, but you can also access the card via standard Java SE and javax.smartcardio API.To do that you need to know the card and card type native APDU commands, here are some examples.

https://joinup.ec.europa.eu/svn/mocca/branches/mocca-1.3.4-cardmgmt/smccTest/src/main/java/at/gv/egiz/smcctest/PKCS15Test.java

Requiring SSL client authentication in a user friendly way in Apache

Requiring SSL client authentication in a user friendly way in Apache

Remember when downgrading to 'SSLVerifyClient require', you also weaken your defense from DOS attacks.

OWASP XSS (Cross-Site Scripting)

XSS is all about scripts sent to a web page and typically it is javascripts.

There are three types of XSS: Stored XSS, Reflected XSS and DOM based XSS

Top 10-2017 A7-Cross-Site Scripting (XSS)

https://www.owasp.org/index.php/XSS_Filter_Evasion_Cheat_Sheet

To protect against XSS, you must have a strong Data Validation:

  1. Accept known good otherwise reject (white list), e.g. phone number, only ascii [a-zA-Z0-9])
  2. Sanitize. i.e. change the user input into an acceptable format. See Input Validation - OWASP Java HTML Sanitizer
  3. Reject known bad (blacklist), e.g. , ' (SQL injection)

OWASP Data Validation

Beside Data Validation, you should add OWASP Security HTTP Headers. And especially 'X-XSS-Protection: 1; mode=block'.

October 27, 2018

Oracle Code One 2018 Hacking and Hardening Java Web Applications

https://s3.amazonaws.com/cmj-presentations/Hacking+and+Hardening+Java+Web+Apps+-+OC12018.pdf

Kali Linux Varient Virtual Machine https://s3.amazonaws.com/cmj-presentations/hacking-uberconf-2016/hhjwa-2016.1-vbox-amd64.ova

https://s3.amazonaws.com/cmj-presentations/hacking-rwx-2017/Hacking_and_Hardening_Java_Web_Applications.pdf

https://github.com/cjudd/wordyninjablog

https://github.com/cjudd/hacking-and-hardening-java-web-apps-workshop

Oracle Code One 2018 Angular for Java developers

https://github.com/bertjan/a4jd

Oracle Code One 2018 Jakarta EE (EE 8) Hands-On Lab

https://github.com/dheffelfinger/j1-hol

See also EE 8 examples at http://magnus-k-karlsson.blogspot.com/2017/11/java-ee-7-and-8-examples-at-github.html

HTTP Caching

https://betterexplained.com/articles/how-to-optimize-your-site-with-http-caching/

Using Expires Headers


ExpiresActive On
ExpiresDefault A0

# 1 YEAR - doesn't change often
<FilesMatch "\.(flv|ico|pdf|avi|mov|ppt|doc|mp3|wmv|wav)$">
ExpiresDefault A31536000
</FilesMatch>

# 1 WEEK - possible to be changed, unlikely
<FilesMatch "\.(jpg|jpeg|png|gif|swf)$">
ExpiresDefault A604800
</FilesMatch>

# 3 HOUR - core content, changes quickly
<FilesMatch "\.(txt|xml|js|css)$">
ExpiresDefault A10800
</FilesMatch>

Using max-age headers


# 1 YEAR
<FilesMatch "\.(flv|ico|pdf|avi|mov|ppt|doc|mp3|wmv|wav)$">
Header set Cache-Control "max-age=31536000, public"
</FilesMatch>

# 1 WEEK
<FilesMatch "\.(jpg|jpeg|png|gif|swf)$">
Header set Cache-Control "max-age=604800, public"
</FilesMatch>

# 3 HOUR
<FilesMatch "\.(txt|xml|js|css)$">
Header set Cache-Control "max-age=10800"
</FilesMatch>

# NEVER CACHE - notice the extra directives
<FilesMatch "\.(html|htm|php|cgi|pl)$">
Header set Cache-Control "max-age=0, private, no-store, no-cache, must-revalidate"
</FilesMatch>

Smart Card Support in RHEL 7

https://rhelblog.redhat.com/2017/09/26/smart-card-support-in-red-hat-enterprise-linux/

https://rhelblog.redhat.com/2017/10/06/picking-your-deployment-architecture/

X.509 Standard set of attributes order

"The order of the relative distinguished names (RDNs) in the subject or issuer DN of a certificate on an ASN.1 level reflects the order in the tree (i.e. top-down):"


    SEQUENCE {
        SET {
            SEQUENCE {
                OBJECT IDENTIFIER=CountryName (2.5.4.6)
                PRINTABLE STRING='US'
            }
        }
        SET {
            SEQUENCE {
                OBJECT IDENTIFIER=OrganizationName (2.5.4.10)
                PRINTABLE STRING='GeoTrust Inc.'
            }
        }
        SET {
            SEQUENCE {
                OBJECT IDENTIFIER=CommonName (2.5.4.3)
                PRINTABLE STRING='GeoTrust Global CA'
            }
        }
    }

C=US,O=GeoTrust Inc.,CN=GeoTrust Global CA

"However, for the string representation of a DN there are two standards: OpenSSL shows the attributes by default as they are actually stored in the certificate, while RFC 2253/4514 reverses the order."

"... the output consists of the string encodings of each RelativeDistinguishedName in the RDNSequence (according to Section 2.2), starting with the last element of the sequence and moving backwards toward the first."

CN=GeoTrust Global CA,O=GeoTrust Inc.,C=US

"Also note that there are certificates "in the wild" which have multiple OUs in their DNs or less common attribute types from RFC 4519 like SERIALNUMBER or UID. I have also seen quite a few certificates, where the RDNs were actually encoded in the wrong order."

Reference:

All HTTP Status Code and How They Fits Together

A good description of all HTTP status code and how they fits together. https://github.com/for-GET/http-decision-diagram

CSRF Support Out-Of-Box in EE 7 (JSF 2.2)

Example https://www.oracle.com/webfolder/technetwork/tutorials/obe/java/JSF-CSRF-Demo/JSF2.2CsrfDemo.html


<?xml version='1.0' encoding='UTF-8' ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:h="http://java.sun.com/jsf/html" xmlns:f="http://java.sun.com/jsf/core">
<h:head>
    <title>JSF 2.2 CSRF</title>
</h:head>
<h:body>
    <h:form>
        <p>Go to a protected page via postback</p>
        <p>
            <h:commandButton id="button_postback" value="Go to protected view" action="/result" />
        </p>
    </h:form>
</h:body>
</html>

If we look at the generated source, we see that JSF has added a javax.faces.ViewState.

"The hidden view state field is very similar to a CSRF token, but it's purpose is to find the session state associated with the request. Basically, that's already what the session id does. But JSF also supports the browser's "back" button. To do so, it stores more than one session state. The JSF implementation I analyzed this morning, Mojarra 2.2.12, uses an LRU cache with up to 15 entries. In other words: you can go back as far as fifteen steps in the history. That should be enough for most use cases."

"The view state token consists of two parts. The first part never changes. It's associated with the session. The second part is associated with a certain point of time in history. In other words: it changes with every post request. In that, it's similar to the one-time-token I mentioned above."


<?xml version='1.0' encoding='UTF-8' ?>
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"><head id="j_idt2">
    <title>JSF 2.2 CSRF</title></head><body>
<form id="j_idt5" name="j_idt5" method="post" action="/example-javaee7/faces/person.xhtml" enctype="application/x-www-form-urlencoded">
<input type="hidden" name="j_idt5" value="j_idt5" />

        <p>Go to a protected page via postback</p>
        <p><input id="button_postback" type="submit" name="button_postback" value="Go to protected view" />
        </p>
        </p><input type="hidden" name="javax.faces.ViewState" id="j_id1:javax.faces.ViewState:0" value="3375434139797034458:2702846074378544391" autocomplete="off" />
</form></body>
</html>

October 26, 2018

How to Set System Properties via File in EAP 6

Use the -P option, e.g. # bin/standalone.sh -P path/to/my/system.properties

Read more https://developer.jboss.org/thread/201184

OWASP Dependency Check

OWASP Dependency Check checks all your dependencies against NVD.

Reference:

Monitoring and Health Check in JBoss EAP 6

Reference:

How to Generate WADL in JBoss EAP 7

The bad news there is no supported way. The best you can get is by CLI.

/deployment=example-javaee7.war/subsystem=jaxrs:read-resource(include-defaults=true, include-runtime=true, recursive=true)
{
    "outcome" => "success",
    "result" => {"rest-resource" => {"se.magnuskkarlsson.person.boundary.PersonResource" => {
        "resource-class" => "se.magnuskkarlsson.person.boundary.PersonResource",
        "rest-resource-paths" => [{
            "resource-path" => "/person",
            "consumes" => undefined,
            "produces" => undefined,
            "java-method" => "java.lang.String se.magnuskkarlsson.person.boundary.PersonResource.hello()",
            "resource-methods" => ["GET /example-javaee7/rest/person"]
        }],
        "sub-resource-locators" => undefined
    }}}
}

You can replace you application name with wildcard to make the expression generic. '/deployment=*/subsystem=jaxrs:read-resource(include-defaults=true, include-runtime=true, recursive=true)'

The other option is using org.jboss.resteasy.wadl.ResteasyWadlServlet, but I did not get that to work with EAP 7.1.0, but the idea of modifying your war seems the wrong way to do it.

Reference:

Exception Handling in JAX-RS 1.1 (EE 6)

ExceptionMapper

Exception/Error handling in JAX-RS is really good, you can write a custom error handler and registered it with @Provider.


import javax.json.Json;
import javax.json.JsonObject;
import javax.ws.rs.core.Response;
import javax.ws.rs.ext.ExceptionMapper;
import javax.ws.rs.ext.Provider;

@Provider
public class IllegalArgumentExceptionMapper implements ExceptionMapper {

    @Override
    public Response toResponse(IllegalArgumentException exception) {
        JsonObject body = Json.createObjectBuilder().add("title", exception.getMessage()).build();
        return Response.status(Response.Status.BAD_REQUEST).entity(body).build();
    }
}

Test


import javax.ws.rs.GET;
import javax.ws.rs.Path;

@Path("/person")
public class PersonResource {

    @GET
    public String hello() {
        throw new IllegalArgumentException("exception from hello");
    }
}

$ curl -i http://localhost:8080/example-javaee7/rest/person
HTTP/1.1 400 Bad Request
Connection: keep-alive
X-Powered-By: Undertow/1
Server: JBoss-EAP/7
Content-Type: application/json
Content-Length: 32
Date: Fri, 26 Oct 2018 17:09:16 GMT

{"title":"exception from hello"}

Standardizing REST Error

Different people write different error message, but there is a standard - Problem Details for HTTP APIs RFC 7807


3.1.  Members of a Problem Details Object

   A problem details object can have the following members:

   o  "type" (string) - A URI reference [RFC3986] that identifies the
      problem type.  This specification encourages that, when
      dereferenced, it provide human-readable documentation for the
      problem type (e.g., using HTML [W3C.REC-html5-20141028]).  When
      this member is not present, its value is assumed to be
      "about:blank".

   o  "title" (string) - A short, human-readable summary of the problem
      type.  It SHOULD NOT change from occurrence to occurrence of the
      problem, except for purposes of localization (e.g., using
      proactive content negotiation; see [RFC7231], Section 3.4).

   o  "status" (number) - The HTTP status code ([RFC7231], Section 6)
      generated by the origin server for this occurrence of the problem.

   o  "detail" (string) - A human-readable explanation specific to this
      occurrence of the problem.

   o  "instance" (string) - A URI reference that identifies the specific
      occurrence of the problem.  It may or may not yield further
      information if dereferenced.

For example:

   HTTP/1.1 400 Bad Request
   Content-Type: application/problem+json
   Content-Language: en

   {
   "type": "https://example.net/validation-error",
   "title": "Your request parameters didn't validate.",
   "invalid-params": [ {
                         "name": "age",
                         "reason": "must be a positive integer"
                       },
                       {
                         "name": "color",
                         "reason": "must be 'green', 'red' or 'blue'"}
                     ]
   }

Reference:

October 25, 2018

JavaEE 8 Deployment Descriptor

Introduction

https://www.oracle.com/webfolder/technetwork/jsc/xml/ns/javaee/index.html

web

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
    version="4.0">

    <servlet>
        <servlet-name>Faces Servlet</servlet-name>
        <servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
        <load-on-startup>1</load-on-startup>
    </servlet>
    <servlet-mapping>
        <servlet-name>Faces Servlet</servlet-name>
        <url-pattern>*.xhtml</url-pattern>
    </servlet-mapping>

    <welcome-file-list>
        <welcome-file>index.xhtml</welcome-file>
    </welcome-file-list>
</web-app>

CDI

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://xmlns.jcp.org/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/beans_2_0.xsd"
    bean-discovery-mode="all" version="2.0">

</beans>

JPA

<?xml version="1.0" encoding="UTF-8"?>
<persistence xmlns="http://xmlns.jcp.org/xml/ns/persistence"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/persistence http://xmlns.jcp.org/xml/ns/persistence/persistence_2_2.xsd"
    version="2.2">

    <persistence-unit name="PROD" transaction-type="JTA">
        <jta-data-source>java:jboss/datasources/MySQL8DS</jta-data-source>
        <class>se.magnuskkarlsson.myproject.entity.User</class>
        <properties>
            <property name="hibernate.dialect" value="org.hibernate.dialect.MySQL8Dialect" />
            <!-- <property name="hibernate.dialect" value="org.hibernate.dialect.H2Dialect" /> -->
            <property name="hibernate.hbm2ddl.auto" value="update" />

            <property name="hibernate.show_sql" value="false" />
            <property name="hibernate.format_sql" value="false" />
            <property name="hibernate.generate_statistics" value="false" />
            <property name="hibernate.cache.infinispan.statistics" value="false" />
        </properties>
    </persistence-unit>
</persistence>

CSRFGuard by OWASP

What is Cross-Site Request Forgery, CSRF?

In previous OWASP Web Top Ten CSRF has always been around, but not in 2017. https://www.owasp.org/index.php/Category:OWASP_Top_Ten_2017_Project. And the reason for that is partly CSRF is now starting to be built in the web framework, but also other vulnerabilities gets more attention, due to technique shift.

On OWASP Cheat Sheet you can read more about CSRF https://www.owasp.org/index.php/OWASP_Cheat_Sheet_Series.

How to Use OWASP CSRFGuard

Maven dependency:


<dependency>
 <groupId>org.owasp</groupId>
 <artifactId>csrfguard</artifactId>
 <version>3.1.0</version>
</dependency>

Activate in web.xml


<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
 version="3.1">

 <listener>
  <listener-class>org.owasp.csrfguard.CsrfGuardServletContextListener</listener-class>
 </listener>
 <listener>
  <listener-class>org.owasp.csrfguard.CsrfGuardHttpSessionListener</listener-class>
 </listener>

 <filter>
  <filter-name>CsrfGuardFilter</filter-name>
  <filter-class>org.owasp.csrfguard.CsrfGuardFilter</filter-class>
 </filter>
 <filter-mapping>
  <filter-name>CsrfGuardFilter</filter-name>
  <url-pattern>/*</url-pattern>
 </filter-mapping>

 <servlet>
  <servlet-name>JavaScriptServlet</servlet-name>
  <servlet-class>org.owasp.csrfguard.servlet.JavaScriptServlet</servlet-class>
 </servlet>
 <servlet-mapping>
  <servlet-name>JavaScriptServlet</servlet-name>
  <url-pattern>/JavaScriptServlet</url-pattern>
 </servlet-mapping>

</web-app>

If you only are rendering your web pages on the server, you can remove JavaScriptServlet.

Configure: Add Owasp.CsrfGuard.properties to your classpath, see https://github.com/aramrami/OWASP-CSRFGuard/blob/9e26fc1b0f992b7eb70357e17690497ee48e2440/csrfguard-test/src/main/webapp/WEB-INF/classes/Owasp.CsrfGuard.properties.

How to use it: Examples from https://github.com/aramrami/OWASP-CSRFGuard/tree/9e26fc1b0f992b7eb70357e17690497ee48e2440/csrfguard-test/src/main/webapp

Exaple HTML


<form id="formTest1" name="formTest1" action="protect.html">
 <input type="text" name="text" value="text"/>
 <input type="submit" name="submit" value="submit"/>
 <input type="hidden" name="<csrf:tokenname/>" value="<csrf:tokenvalue uri="protect.html"/>"/>
</form>

Example JSP


<csrf:form id="formTest2" name="formTest2" action="protect.html">
 <input type="text" name="text" value="text"/>
 <input type="submit" name="submit" value="submit"/>
</csrf:form>

Read more https://github.com/aramrami/OWASP-CSRFGuard/tree/9e26fc1b0f992b7eb70357e17690497ee48e2440

And https://www.owasp.org/index.php/Category:OWASP_CSRFGuard_Project#tab=Main

October 24, 2018

How To Install VirtualBox on Fedora 28

Prerequisite


# cat /etc/fedora-release
Fedora release 28 (Twenty Eight)

Installation

https://www.virtualbox.org/wiki/Linux_Downloads


$ sudo -u root bash
# wget https://download.virtualbox.org/virtualbox/rpm/fedora/virtualbox.repo -P /etc/yum.repos.d/
# yum install VirtualBox

OpenJDK Mission Control 7 on Fedora 28

Oracle has open sourced the Mission Control.

To download prebuild: http://jdk.java.net/jmc/

Homepage OpenJDK Mission Control: http://openjdk.java.net/projects/jmc/

Building from the source, core developer blog http://hirt.se/blog/?p=947.

New feature in OpenJDK Mission Control 7 http://hirt.se/blog/?p=211

Oracle (commercial) documentation and homepage https://docs.oracle.com/javacomponents/