Wednesday, December 30, 2015

Understand spring security easily – concept view

Spring security is designed to provide both authentication and authorization to Java applications.

This article mainly try to describe spring security from a general concept view, give you a whole picture of how the spring security works in most usage. Other articles are:

Understand spring security easily – developer view (to be continued)  

Understand spring security easily – annotation example (to be continued)  

0. Basic senario

In this serial we only focus on the most popular senario, web application security and using username+password to get access. Passwords are stored in database. This article is based on spring security  4.x

1. key concept

Credential – namely password in our username + password senario.

Princple – you can think it’s a kind of identification of a user.  It includes username, password and all the authorities that this user has. Most authentication mechanisms withing spring security return an instance of UserDetails as the principal.

UserDetails – just an interface in package org.springframework.security.core.userdetails. Like said above, an instance of UserDetails always used as identification of a user. What does this mean? It means when you read you database get all information for a user, you finally get a instance of UserDetails.

3 most used methods of UserDetails are getUserName(),getPassword and getAuthorities().

Spring security provide a implementation, org.springframework.security.core.userdetails.User. But in practicle, in a spring project with ORM, you normally will have your own implementation of UserDetails. It’s often looks like:

public class CustomUser extends YourUserEntity implements UserDetails {
 //...
}

Spring security will use UserDetails instance created according to database to test browser provided info. Now the question is, “create UserDetails instance”, where does this happen?  In UserDetailsService.

UserDetailsService – This interface only has one method,UserDetails loadUserByUsername(String username)In real project you also need to provide an implementation of this interface and it often looks like:

public class CustomUserDetailsService implements UserDetailsService {
  @Override
  UserDetails loadUserByUsername(String username) {
    // access database by DAO or Spring data repository
    CustomUser userInDatabase = (CustomUser)yourUserEntityRepository.findByUsername(username);
    return userInDatabase;
  }
}

This is the place you put your own code to access database to load user information.(We define CustomUser as a child of YourUserEntity, remember?)

1. Filter Chain

The spring security is mainly build on servlet filters. Filter has a doFilter(…,FilterChain chain) . In method doFilter , there’s always a call to chain.doFilter(), which devides the filter into 2 pieces. Code before chain.doFilter() run before the request reach any servlet, code after chain.doFilter() run after the request being processed and before response send back to browser.

There are many filters in spring security and the order of these filters matters. Here is a filter list from spring security reference. There are 10+ filters in spring security, but check several key filters:

  • UsernamePasswordAuthenticationFilter – This filter get your http post username + password and create and verify the password.
  • ExceptionTranslationFilter – If not authenticated, jump to login page.
  • FilterSecurityInterceptor – if the logined user has right to access the target url. (Authorization)
  • These 3 filters are key to understand the work flow of spring security authentication and authorization.

Tuesday, December 29, 2015

"Config method" in Spring framework

1. Concept

What is config method in Spring? Any method that is anotated by @autowired is config method.

What’s the difference between a normal method and a config method in spring? Config method will be automatically  invoked when the bean instance created, after constructor but before @PostConstruct. The parameters of config method will be autowired from the application context. 

The name of the method doen’t matter and parameter number doesn’t matter. In fact we often use @autowired before setter method, that’s  just a special case of spring config method.

2. Usage of config method

Genetic config method is not widely use as field injection, setter injection or constructor injection,  but config method is used  in spring security.  According to spring security official reference here, the first step to config spring security is to extend from WebSecurityConfigurerAdapter like below.

import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.context.annotation.*;
import org.springframework.security.config.annotation.authentication.builders.*;
import org.springframework.security.config.annotation.web.configuration.*;

@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {

  @Autowired
  public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
    auth.inMemoryAuthentication().withUser("user").password("password").roles("USER");
  }
}

This is a good example of using config method.  config method will be automatically invoked when bean instantiated, that’s why the document said

The name of the configureGlobal method is not important.

Because it just a config method, and will be automatically invoked with a AuthenticatonManagerBuilder bean from context. The purpose of this method is just to using AuthenticationManagerBuilder to setup authentication provider before real logic begins.

3. See also

spring framework javadoc of @Autowired

Wednesday, December 23, 2015

Break down package java.util.concurrent.locks

Since JDK 5, Java introduced the most powerful enhancement for concurrence, the package java.util.concurrent.This package contain 2 subpackages, one of them is java.util.concurrent.locks, which provides the notion of locks for synchorization. (BTW, the other subpackage is java.util.concurrent.atomic, which is a small toolkit of classes that support lock-free thread-safe programming on single variables, making common operation like i++ atomic in concurrent environment)

This article will give a big picture of the package java.util.concurrent.locks. Help you get a better understanding of this package.

This article suppose you have already know basic usage of the locks, so will not try to go into usage details, but to focus on the realations of all interfaces and classes as a whole.

1. Hirerarchy diagram

java_locks

There are only 3 interfaces in this package(green boxes). The diagram also has 4 concreate classes. Only the 2 classes in pink are usually created by keyword new directly, the rest two can not create by a direct new, because their constructor are not public but protected.

2. More explanation

The Condition instance is used to replace the low-level synchronization monitor. (If you want to know more about Java build-in low level synchronization mechanism, see here)

There is no public implementation of this interface in JDK. The only way to create Condition instance is  by newCondition() method of a Lock objects.

The methods await() and signal() are designed to replace the built-in wait() and notify() of every java Object.

The interfaces Lock and ReadWriteLock has no parent-child relation! Although Lock may sound like the parent of ReadWriteLock, but in fact they have no relations at all.

Since all locks implementation are reentrant, which means a thread already has lock can successfully call lock() again without blocking. So there are ways to get how lock hold count in program to know how many times to call unlock(). See the methods getHoldCount() and getReadHoldCount()/getWriteHoldCount().

ReentrantReadWriteLock.ReadLock  and ReentrantReadWriteLock.WriteLock (2 white boxes in diagram),can not be initialized by keyword new since they don’t have public constructors. So the instaces of these two classes can not live independently, but always accompanied by a ReentrantReadWriteLock instance.

Hope now you have a more clear view of package java.util.concurrent.locks.

Wednesday, December 16, 2015

Use Spring Test without @RunWith(SpringJUnit4ClassRunner.class)

This is a new feature from Spring framework 4.2. Now you can use other JUnit's runners,like Parameterized or MockitoJUnitRunner but without losing spring test benefits. (with all the features you love with spring-test like spring  Dependency Injection , Auto-rollback Transaction for test and etc).

In this article, a simple hello world level JUnit test case is provided with JUnit Parameterized runner, with spring-test support enabled.

0. What you need

  • JDK 1.7 +
  • Spring framework 4.2 + ( 4.2.1.RELEASE is used in this demo)
  • Maven 3.2+ (This demo is a maven project, but maven is not necessary for enable Spring-test support in other JUnit runners)

1. Define pom.xml

<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>com.shengwang.demo</groupId>
  <artifactId>spring-test-simple</artifactId>
  <version>1</version>
  <packaging>jar</packaging>

  <name>spring-test-simple</name>
  <url>http://maven.apache.org</url>

  <dependencies>
    <!-- Spring framework -->
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-context</artifactId>
      <version>4.2.1.RELEASE</version>
    </dependency>

    <!-- Spring test -->
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-test</artifactId>
      <version>4.2.1.RELEASE</version>
      <scope>test</scope>
    </dependency>
    
    <!-- JUnit test -->
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>4.11</version>
      <scope>test</scope>
    </dependency>

  </dependencies>
  
  <build>
    <plugins>
      <!-- Use Java 1.7 -->
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-compiler-plugin</artifactId>
        <version>2.5.1</version>
        <configuration>
          <source>1.7</source>
          <target>1.7</target>
        </configuration>
      </plugin>
    </plugins>
  </build>
</project>

The pom specifies 3 dependencies, spring-context, spring-test and junit. Also it specify the Java version to 1.7.

2. Define Java Class

There are 3 classes in this demo. First is HelloService.java, which is a Spring bean as test target. 

package com.shengwang.demo;

import org.springframework.stereotype.Service;

@Service
public class HelloService {

  public String sayHello(String name) {
    return "Hello " + name;
  }
}

The second is JavaConfig.java, as Spring context configuration.

package com.shengwang.demo;

import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;

@Configuration
@ComponentScan
public class JavaConfig {}

The Last is the JUnit test case HelloServiceTest.java use Parameterized as runner.

package com.shengwang.demo;

import java.util.Arrays;
import java.util.Collection;

import org.junit.ClassRule;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import org.junit.runners.Parameterized.Parameters;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.rules.SpringClassRule;
import org.springframework.test.context.junit4.rules.SpringMethodRule;

@RunWith(Parameterized.class)
@ContextConfiguration(classes=JavaConfig.class)  // specify context config
public class HelloServiceTest {
  
  // -------------------------------------------
  //  spring test support requirement from 4.2
  // -------------------------------------------
  @ClassRule
  public static final SpringClassRule SPRING_CLASS_RULE= new SpringClassRule();
  @Rule
  public final SpringMethodRule  springMethodRule = new SpringMethodRule();
  // -------------------------------------------
  //  spring test support requirement over
  // -------------------------------------------
  
  private String name;
  
  @Autowired
  HelloService service;

  public HelloServiceTest(String name) {
    this.name = name;
  }
  
  @Parameters
  public static Collection<String[]> data() {
    return Arrays.asList(new String[][] {
        {"Tom"},{"Jerry"}  
    });
  }
  
  @Test
  public void testSayHello() {
    service.sayHello(name);
  }
  
}

The test case enable spring-test support by 3 steps:

  1. 1. Use @ContextConfiguration to config Spring TestContext .
  2. 2. Add a SpringClassRule static variable
  3. 3. Add a SpringMethodRule field variable

The project's hierarchy looks like below:

image_thumb5

Now the test get all abilities from spring-test. The @Autowired dependency injection works perfectly.

image_thumb2

Wednesday, December 9, 2015

Most used Hibernate properties during development

Hibernate has many properties that can be very helpful during development phrase. In this article we list some most used hibernate properties  used when developing/testing persistence layer applications.

1. Meaning of most used hibernate properties

1.1 Print out Hibernate created SQL

hibernate.show_sql = true

1.2 Automatic create tables according to entities

hibernate.hbm2ddl.auto = create

Change to create-drop if you want to drop the created table when application over. Useful for prototype and testing.

1.3 Run SQL scripts at beginning of application

hibernate.hbm2ddl.import_files = /path/of/sqlfile

This's most used to insert some test data before unit test case running.

1.4 Use c3p0 connection pool

hibernate.c3p0.min_size=5                              // minimum connections in pool
hibernate.c3p0.max_size=20                           // maximum connections in pool
hibernate.c3p0.timeout=1800                        // time out to remove idle connection. In seconds
hibernate.c3p0.max_statements=50          // cache prepared statements
hibernate.c3p0.idle_test_period=3000      // how often to validate a connection. In seconds.

1.5 Use Improved Naming Strategy ("clientAddress"->"client_address")

hibernate.ejb.naming_strategy  = org.hibernate.cfg.ImprovedNamingStrategy

2. Use Hibernate properties in JPA persistence.xml

If use Hibernate as JPA provider, you can set hibernate properties in persistence.xml.

<?xml version="1.0" encoding="UTF-8"?>
<persistence version="2.1"
  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_1.xsd">
  <persistence-unit name="persistenceUnitName"  transaction-type="RESOURCE_LOCAL">
    <provider>org.hibernate.ejb.HibernatePersistence</provider>
    <exclude-unlisted-classes>false</exclude-unlisted-classes>
    <properties>
      <!-- common jdbc configuration -->
      <property name="javax.persistence.jdbc.driver" value="org.h2.Driver" />
      <property name="javax.persistence.jdbc.url" value="jdbc:h2:mem:mydb" />
      <property name="javax.persistence.jdbc.user" value="sa" />
      <property name="javax.persistence.jdbc.password" value="" />
    
      <!-- ==================== -->
      <!-- hibernate properties -->
      <!-- ==================== -->
      <property name="hibernate.hbm2ddl.auto" value="create" />
      <property name="hibernate.show_sql" value="true"/>
      <property name="hibernate.ejb.naming_strategy" value="org.hibernate.cfg.ImprovedNamingStrategy"/>
    </properties>
  </persistence-unit>
</persistence>

3. Use Hibernate properties in Spring Boot


Spring boot does a lot of auto configurations.  So there is no need to use hibernate.hbm2ddl.import_files to set a sql script file location to run. Just put the sql script file as src/main/resources/import.sql. Spring boot will auto config it if spring-boot-starter-data-jpa is in pom.


There is also no need for hibernate.hbm2ddl.auto. Spring boot will also auto detect if the database used is a embedded one, like HSQL, H2 or Derby, or external database. If a embedded database is used,  default is create-drop. Otherwise for external database,  default is none. (No tables will be auto created). You can set this behavior in spring boot's  configuration file application.properties with spring.jpa.hibernate.ddl-auto= create, for example.


Other hibernate properties can be se with prefix 'spring.jpa.properties.' , such as add following lines in /src/main/resources/application.properties 


# hibernate special properties, with prefix "spring.jpa.properties."
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.H2Dialect
spring.jpa.properties.hibernate.c3p0.min_size=3
spring.jpa.properties.hibernate.c3p0.max_size=10
spring.jpa.properties.hibernate.show_sql=true

4. What's More


For complete hibernate 4.x configuration properties, check official hibernate reference.

Tuesday, December 1, 2015

Remote Debug in Eclipse

Remote debug a Java application means the application run on a different VM rather than the one used for Eclipse. The Java application can run on the same host of you Eclipse as a separate process or on remote host.

In practical remote debug happens when there are some external environments in production that you don't have in your development environment. Or you code works in development environment, but has problems in production environment.

Remote debug can let you connect to the running applications and do what you can do for debug, like breakpoint/single-step-run/watch variables, just like debug a local application.

To make remote debug possible, extra JVM options have to be set when running the application remotely.

In this article, we create a hello world Java application, run it with command line, then use Eclipse to connect to it. In fact this hello world application can run on any remote host, but for demo it will run on the same host as where Eclipse is.

1. Create Project in Eclipse

Create a Java project in Eclipse with a main class.

package com.shengwang.demo;

import java.io.Console;

public class DemoMain {

public static void main(String[] args) {
Console console = System.console();
console.readLine("Please hit Enter to continue...");
System.out.println("Hello World! - Remote Debug in Eclipse");
}
}

The demo project only has only 1 DemoMain.java.


image


Compile the project and it's ready to run. In your case this step means you finish your project's coding in Eclipse.


2. Run with extra JVM options


To enable remote debug, application has to be run with extra JVM options.


-Xdebug -Xrunjdwp:server=y,transport=dt_socket,suspend=n,address=0.0.0.0:8000


JDWP is the agent for debug and it will listen on port 8000, which is the default debug port in most case.


image


3.  Run Debug in Eclipse


Now the application is running, let's remotely debug it.


First select you project in Eclipse's package explorer. (make it easy to create debug configuration)


image


Then  click "Run-> Debug Configurations" from menu. Double-click "Remote Java Application" to create a debug configuration for the selected project.


image


Make sure the host and port is where you application runs and debug server specified port.  Then hit "Debug" to connect to the remote debug application. Almost done, you can debug the remote like you usually do. Let's set a break point on our source code.


image



Go back to our running application and hit enter to let it continue, the break point get hit and eclipse automatically switch Debug Perspective like local debugging.


image

Powered by Blogger.

About The Author

My Photo
Has been a senior software developer, project manager for 10+ years. Dedicate himself to Alcatel-Lucent and China Telecom for delivering software solutions.

Pages

Unordered List