Configuring spring security
I have written another post listing how to construct your login and logout pages to work with spring-security. It’s important that you read this post first if you’re new to spring-security.
Security in web applications is a big concern. More often than not developers miss securing a few pages here and there. These pages aren’t a huge concern till someone finds them and starts to mess with your system using them. Then the scramble to fix and re-evaluate your security starts. So, why don’t we secure ALL our pages instead of most of them? And why don’t we allow access to only those which we define and block access to everything else? This inverted model of security is what has been implemented in spring security. It’s a beautiful and powerful solution to securing web apps. Yes, i’m a spring fanboi but you’ll love spring security too once you love it.
As with anything else related to spring the learning curve on spring-security is just as steep. But once you get the hang of it, it’s easy peasy and you can use the same configuration over and over again in your web apps. It’s also worthwhile to mention that spring-security’s documentation could be a LOT better in terms of content not to mention better laid out.
Let’s start with the web.xml. I’m not going to list out any spring only configuration because if you still need to do that manually, you’re in trouble, you should have a template application ready to copy from at anytime.
<context-param> <param-name>contextConfigLocation</param-name> <param-value> /WEB-INF/security-applicationContext.xml, /WEB-INF/applicationContext.xml </param-value> </context-param> <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>
Notice how we map ALL url’s to the spring-security servlet.
In your security-applicationContext.xml :
<security:http auto-config="true"> <!-- Don't set any role restrictions on login.jsp --> <security:intercept-url pattern="/login.jsp" access="IS_AUTHENTICATED_ANONYMOUSLY" /> <!-- Restrict access to ALL other pages --> <security:intercept-url pattern="/**" access="ROLE_USER" /> <!-- Set the login page and what to do if login fails --> <security:form-login login-page="/login.jsp" authentication-failure-url="/login.jsp?login_error=1" /> <!-- Set the logout page and where to go after logout is successful --> <security:logout logout-url="/logout" logout-success-url="/logoutSuccess.jsp" /> </security:http> <!-- Configure the authentication provider --> <security:authentication-provider> <security:jdbc-user-service data-source-ref="dataSource" /> </security:authentication-provider>
The auto-config attribute basically tells spring-security to configure default settings for itself.
The login.jsp is allowed to be access from ANY role, ofcourse restricting access to it would mean that no one would be able to reach even the login page. Note how we’re using a jsp here instead of a spring managed controller. The login page doesn’t need to be a spring managed controller at all, I haven’t tried it that way but I don’t think it’ll be too much of a problem anyway.
We also tell spring-security to restrict access to ALL url’s to only those users who have the role ROLE_USER. Notice how we tell spring-security to get all user authentication details from the dataSource. This requires that a dataSource be created first. You should be aware that the default authentication provider requires the database structure to be in a certain way :
CREATE TABLE users ( username character varying(50) NOT NULL, "password" character varying(50) NOT NULL, enabled boolean NOT NULL, CONSTRAINT users_pkey PRIMARY KEY (username) ) WITH (OIDS=FALSE); CREATE TABLE authorities ( username character varying(50) NOT NULL, authority character varying(50) NOT NULL, CONSTRAINT fk_authorities_users FOREIGN KEY (username) REFERENCES users (username) MATCH SIMPLE ON UPDATE NO ACTION ON DELETE NO ACTION ) WITH (OIDS=FALSE); CREATE UNIQUE INDEX ix_auth_username ON authorities USING btree (username, authority);
Some dummy data for you to work with :
INSERT INTO users VALUES ('user1', 'pass1', true); INSERT INTO users VALUES ('user2', 'pass2', true); INSERT INTO authorities VALUES ('user1', 'ROLE_USER'); INSERT INTO authorities VALUES ('user1', 'ROLE_ADMIN'); INSERT INTO authorities VALUES ('user2', 'ROLE_USER');
To show your users that they do not have access to a particular page you must add access-denied-page to the http element. Something like this :
<security:http auto-config="true" access-denied-page="/accessDenied.html"> </security:http>
That sets you up with a minimalistic spring-security configuration to get started. I’ll write a post to detail how to implement a custom authentication provider soon since I imagine thats what most of us want to do.