Programming     Travel Logs     Life Is Good     Surfing Online     About Me
Specific knowledge is found by pursuing your genuine curiosity and passion rather than whatever is hot right now.
-Naval Ravikant
2018-06-11 22:08:46

Copy this link when reproducing:
http://www.casperlee.com/en/y/blog/181

I've finished the display portion of the code in my "Today in History" application. Now it is time to start the management portion of the code. For sure, I don't want any users, especially anonymous users, to be able to manage my application. So, before implementing the management portion of the code, let's find out how to use Spring Security to protect my application from being accessed by anonymous users.

/Images/20170925/01.jpg

/Images/20170925/02.jpg

/Images/20170925/03.jpg

/Images/20170925/04.jpg

/Images/20170925/05.jpg

/Images/20170925/06.jpg

1. Download Spring Security.

    I. Open a web browser, navigate to http://projects.spring.io/spring-security/, and find the Maven dependencies for Spring Security.

    II. Use maven project and the following dependencies to download Spring Security and other related libraries:

<dependencies>
    ...

    <dependency>
        <groupId>org.springframework.security</groupId>
        <artifactId>spring-security-web</artifactId>
        <version>5.0.0.M4</version>
    </dependency>
        
    <dependency>
        <groupId>org.springframework.security</groupId>
        <artifactId>spring-security-config</artifactId>
        <version>5.0.0.M4</version>
    </dependency>

    <dependency>
        <groupId>org.springframework.security</groupId>
        <artifactId>spring-security-taglibs</artifactId>
        <version>5.0.0.M4</version>
    </dependency>

    ...
  </dependencies>
  
  <repositories>
    <repository>
        <id>spring-milestones</id>
        <name>Spring Milestones</name>
        <url>https://repo.spring.io/libs-milestone</url>
        <snapshots>
            <enabled>false</enabled>
        </snapshots>
    </repository>
  </repositories>

FYI: Check the link http://www.casperlee.com/x/y/blog/82 for more information about using Maven project to download libraries.

2. Copy the libraries which were just downloaded into the folder "\WebContent\WEB-INF\lib", and refresh the "today" project.

FYI: Here is the list of libraries I've downloaded:

    spring-security-core-5.0.0.M4.jar
    spring-security-web-5.0.0.M4.jar
    spring-security-acl-5.0.0.M4.jar
    spring-security-config-5.0.0.M4.jar
    spring-security-taglibs-5.0.0.M4.jar

3. Put the following lines into the configuration file "WebContent\WEB-INF\web.xml" to indicate:

    I. I want to use the built-in filter org.springframework.web.filter.DelegatingFilterProxy.
    II. the configuration file for the filter is located in "/WEB-INF/config/".

<!--
     - Location of the XML file that defines the root application context
     - Applied by ContextLoaderListener.
  -->
  <context-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>
      /WEB-INF/config/*.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>

  <!--
     - Loads the root application context of this web app at startup.
     - The application context is then available via
     - WebApplicationContextUtils.getWebApplicationContext(servletContext).
  -->
  <listener>
    <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
  </listener>

4. Create a file named "spring-security.xml" in the folder "WebContent\WEB-INF\config", and put the following lines into it to indicate:

    I. I want Spring Security to protect all requests to URLs which match the pattern "/admin/**", and only users which have the role of "ADMIN" can access them. This means it'll only protect the management portion of application.
    II. I want to use the built-in service "org.springframework.security.core.userdetails.jdbc.JdbcDaoImpl", and the service will use a data source named "dataSource".

<b:beans xmlns="http://www.springframework.org/schema/security"
		 xmlns:b="http://www.springframework.org/schema/beans"
		 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
		 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">
		     
    <http>
      <intercept-url pattern="/admin/**" access="hasRole('ADMIN')" />
      <form-login />
      <remember-me />
      <logout logout-success-url="/" />
    </http>
    
    <authentication-manager>
      <authentication-provider user-service-ref='myUserDetailsService'/>
    </authentication-manager>
    
    <b:bean id="myUserDetailsService"
        class="org.springframework.security.core.userdetails.jdbc.JdbcDaoImpl">
        
      <b:property name="dataSource" ref="dataSource"/>
    </b:bean>
</b:beans>

FYI: In case you forgot, here is the data source I've defined in "springmvc-config.xml":

    <bean id="dataSource" class="org.apache.commons.dbcp2.BasicDataSource"
        destroy-method="close">
      <property name="driverClassName" value="com.mysql.jdbc.Driver" />
      <property name="url" value="jdbc:mysql://localhost:3306/DayDB" />
      <property name="username" value="root" />
      <property name="password" value="[Password]" />
    </bean>

5. Clearly the service "org.springframework.security.core.userdetails.jdbc.JdbcDaoImpl" requests a data structure in the database. In the Project Explorer, expand "Java Resources -> Libraries -> Web App Libraries -> spring-security-core-5.0.0.M4.jar -> org.springframework.security.core.userdetails.jdbc", there is a file named "users.ddl". Open the file "users.ddl", we get the SQL commands to create related tables:

create table users(username varchar_ignorecase(50) not null primary key,password varchar_ignorecase(500) 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);

6. Because I'm using MySQL database, I need to adjust these SQL commands to meet the needs of MySQL. Use the following commands to create the tables:

mysql> create table Users (
    -> username varchar(50) not null primary key,
    -> password varchar(50) not null,
    -> enabled boolean not null
    -> );
mysql> insert into Users values (
    -> 'admin', 'admin', true);
	
mysql> create table authorities (
    -> username varchar(50) not null,
    -> authority varchar(50) not null,
    -> constraint fk_authorities_users foreign key(username) references users(username)
    -> );
mysql> create unique index ix_auth_username on authorities (username, authority);

FYI: Check the link http://www.casperlee.com/en/l/blog/90 for more information about dealing with MySQL database.

7. Insert user and role information to the tables:

mysql> select * from users;
+----------+----------+---------+
| username | password | enabled |
+----------+----------+---------+
| admin    | admin    |       1 |
| c        | c        |       1 |
+----------+----------+---------+
2 rows in set (0.00 sec)

mysql> select * from authorities;
+----------+------------+
| username | authority  |
+----------+------------+
| ADMIN    | ROLE_ADMIN |
| C        | ROLE_USER  |
+----------+------------+
2 rows in set (0.00 sec)

8. Right click on the "today" project, select "Run As -> Run on Server" on the popped menu to test. Navigate to "http://localhost:[YourPortNum]/com.casperlee.today/admin" to see what will happen:

/Images/20170925/101.jpg

9. Yeah! It works!