Spring Security
Coverage
In this first part, I’m going to cover integrating Spring Security into a web application to authenticate users stored in a MySQL database.
Introduction
I’ve developed a project named Passport with which I plan to utilize in any project requiring users. Rather than constantly having to re-write the storage and access faculties, I can import the UserService and go from there. This works great in a controlled environment, so I decided to test it by creating a new project using Spring Security to authenticate against the user store. I frequently use Spring Security, and figured it’d save me the hassle of writing session code for web apps.
Fail
The problem I ran into is that Spring Security cannot be configured to use a specific method in a specific class to authenticate users. I need a new way to access the database to verify user’s identity, while still finding value in Passport.
Answer
The solution is easy. In accessing a MySQL data store, Spring Security can be configured to use specific queries. Even better, to ensure password privacy, it can use a hashing algorithm (sha) to manipulate the password stored.
First, here is the entire security-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:p="http: www.springframework.org schema p" xmlns:security="http: www.springframework.org schema security" xsi:schemaLocation="http: www.springframework.org schema beans http:= www.springframework.org schema beans spring-beans-3.1.xsd http:= www.springframework.org schema context http:= www.springframework.org schema context spring-context-3.1.xsd http:= www.springframework.org schema security http:= www.springframework.org schema security spring-security-3.1.xsd"> <!-- Import the dynamic properties --> <context:property-placeholder location="WEB-INF connections.properties" /> <!-- Scan for annotated methods --> <security:global-method-security secured-annotations="enabled" /> <security:http auto-config="true"> <!-- Restrict URLs based on role --> <security:intercept-url pattern=" secured" access="IS_AUTHENTICATED_FULLY" /> </security:http> <security:authentication-manager> <security:authentication-provider> <security:password-encoder hash="sha" /> <security:jdbc-user-service data-source-ref="myDataSource" users-by-username-query="select= username, password, true from users where username=" /> </security:authentication-provider> </security:authentication-manager> <!-- MySql --> <bean id= "myDataSource" class= " org.springframework.jdbc.datasource.DriverManagerDataSource"> <property name= " driverClassName" value= " com.mysql.jdbc.Driver" /> <property name= " url" value= " ${datasource.url}" /> <property name= " username" value= " ${datasource.user}" /> <property name= " password" value= " ${datasource.pw}" /> </bean> </beans>
As you will hopefully notice, I’m importing the volatile datastore attributes through the PropertyPlaceholderConfigurer, accessing the values with ${}. This allows for easy changes when used in different environments.
Secondly, the security:password-encoder property defines the hashing algorithm used for the password. Other options include plaintext, sha-256, md4, and md5.
Lastly, two queries are specified to be used by Spring Security — users-by-username-query and authorities-by-username-query. The first is obvious. The latter authorities by username, which is use to authenticate roles for users. This is very important, as authentication is primarily based against a user’s roles.
Solution
So, once we try to go to any URLs beneath /secured, we will need to be authenticated. Spring will generate the login page for us, and prevent access without a successful login.
Next, how to access the user’s information in Java.