betacode

Простой веб-приложение Java с использованием Spring MVC, Spring Security и Spring JDBC

  1. Demo
  2. Приготовить базу данных
  3. Создать Project
  4. Конфигурация Maven & web.xml
  5. Конфигурация Spring MVC & Security
  6. Классы учатсвующие в безопасности (Security)
  7. Spring MVC Controller
  8. JSP Pages
  9. Конфигурация и запуск приложения
  10. Fix Error!

1. Demo

Просмотр приложения:

2. Приготовить базу данных

  • ORACLE:
-- Create table
create table USERS
(
  USERNAME VARCHAR2(36) not null,
  PASSWORD VARCHAR2(36) not null,
  ENABLED  NUMBER(1) not null
) ;

alter table USERS
  add constraint USER_PK primary key (USERNAME);

---------------------

-- Create table
create table USER_ROLES
(
  ROLE_ID   VARCHAR2(50) not null,
  USERNAME  VARCHAR2(36) not null,
  USER_ROLE VARCHAR2(30) not null
) ;
 
alter table USER_ROLES
  add constraint USER_ROLE_PK primary key (ROLE_ID);

alter table USER_ROLES
  add constraint USER_ROLE_UK unique (USERNAME, USER_ROLE);
 
-------------------------------
 
insert into users (USERNAME, PASSWORD, ENABLED)
values ('dbuser1', '12345', 1);

insert into users (USERNAME, PASSWORD, ENABLED)
values ('dbadmin1', '12345', 1);  


insert into User_Roles (ROLE_ID, USERNAME, USER_ROLE)
values ('1', 'dbuser1', 'USER');

insert into User_Roles (ROLE_ID, USERNAME, USER_ROLE)
values ('2', 'dbadmin1', 'ADMIN');

insert into User_Roles (ROLE_ID, USERNAME, USER_ROLE)
values ('3', 'dbadmin1', 'USER');

-------------------------------
Commit;
  • MySQL & SQL Server:
-- Create table
create table USERS
(
 USERNAME VARCHAR(36) not null,
 PASSWORD VARCHAR(36) not null,
 ENABLED  smallint not null
) ;

alter table USERS
 add constraint USER_PK primary key (USERNAME);

---------------------

-- Create table
create table USER_ROLES
(
 ROLE_ID   VARCHAR(50) not null,
 USERNAME  VARCHAR(36) not null,
 USER_ROLE VARCHAR(30) not null
) ;

alter table USER_ROLES
 add constraint USER_ROLE_PK primary key (ROLE_ID);

alter table USER_ROLES
 add constraint USER_ROLE_UK unique (USERNAME, USER_ROLE);

-------------------------------

insert into users (USERNAME, PASSWORD, ENABLED)
values ('dbuser1', '12345', 1);

insert into users (USERNAME, PASSWORD, ENABLED)
values ('dbadmin1', '12345', 1);  


insert into User_Roles (ROLE_ID, USERNAME, USER_ROLE)
values ('1', 'dbuser1', 'USER');

insert into User_Roles (ROLE_ID, USERNAME, USER_ROLE)
values ('2', 'dbadmin1', 'ADMIN');

insert into User_Roles (ROLE_ID, USERNAME, USER_ROLE)
values ('3', 'dbadmin1', 'USER');

3. Создать Project

  • File/New/Other...
Введите:
  • Group ID: org.o7planning
  • Artifact ID: SpringMVCAnnotationSecurity
  • Package: org.o7planning.tutorial.springmvcsecurity
Project создан:
Не беспокойтесь об оповещении ошибки когда Project только создан. Это потому что вы еще не объявили библиотеку Servlet.
Редактировать структуру project:
Удалить файл index.jsp.
Нажать на правую кнопку мыши на project и выбрать Properties:

4. Конфигурация Maven & web.xml

Конфигурируйте, используя WebApp 3.x.
web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 xmlns="http://java.sun.com/xml/ns/javaee"
 xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
          http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
 id="WebApp_ID" version="3.0">

 <display-name>Spring MVC Security</display-name>
 

</web-app>
Maven:
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/maven-v4_0_0.xsd">

<modelVersion>4.0.0</modelVersion>
<groupId>org.o7planning</groupId>
<artifactId>SpringMVCAnnotationSecurity</artifactId>
<packaging>war</packaging>
<version>0.0.1-SNAPSHOT</version>
<name>SpringMVCAnnotationSecurity Maven Webapp</name>
<url>http://maven.apache.org</url>




  <properties>
      <!-- Generic properties -->
      <java.version>1.7</java.version>
      <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
      <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
  </properties>


  <repositories>
      <!-- Repository for ORACLE JDBC Driver -->
      <repository>
          <id>codelds</id>
          <url>https://code.lds.org/nexus/content/groups/main-repo</url>
      </repository>
  </repositories>

  <dependencies>

      <!-- Spring framework START -->
      <!-- http://mvnrepository.com/artifact/org.springframework/spring-core -->
      <dependency>
          <groupId>org.springframework</groupId>
          <artifactId>spring-core</artifactId>
          <version>4.2.5.RELEASE</version>
      </dependency>

      <!-- http://mvnrepository.com/artifact/org.springframework/spring-web -->
      <dependency>
          <groupId>org.springframework</groupId>
          <artifactId>spring-web</artifactId>
          <version>4.2.5.RELEASE</version>
      </dependency>

      <!-- http://mvnrepository.com/artifact/org.springframework/spring-webmvc -->
      <dependency>
          <groupId>org.springframework</groupId>
          <artifactId>spring-webmvc</artifactId>
          <version>4.2.5.RELEASE</version>
      </dependency>
    
    

      <!-- http://mvnrepository.com/artifact/org.springframework/spring-jdbc -->
      <dependency>
          <groupId>org.springframework</groupId>
          <artifactId>spring-jdbc</artifactId>
          <version>4.2.5.RELEASE</version>
      </dependency>

    
      <!-- Spring framework END -->


      <!-- Spring Security Artifacts - START -->
      <!-- http://mvnrepository.com/artifact/org.springframework.security/spring-security-web -->
      <dependency>
          <groupId>org.springframework.security</groupId>
          <artifactId>spring-security-web</artifactId>
          <version>4.0.4.RELEASE</version>
      </dependency>

      <!-- http://mvnrepository.com/artifact/org.springframework.security/spring-security-config -->
      <dependency>
          <groupId>org.springframework.security</groupId>
          <artifactId>spring-security-config</artifactId>
          <version>4.0.4.RELEASE</version>
      </dependency>
      <!-- Spring Security Artifacts - END -->

      <!-- Jstl for jsp page -->
      <!-- http://mvnrepository.com/artifact/javax.servlet/jstl -->
      <dependency>
          <groupId>javax.servlet</groupId>
          <artifactId>jstl</artifactId>
          <version>1.2</version>
      </dependency>

      <!-- Servlet API -->
      <!-- http://mvnrepository.com/artifact/javax.servlet/javax.servlet-api -->
      <dependency>
          <groupId>javax.servlet</groupId>
          <artifactId>javax.servlet-api</artifactId>
          <version>3.1.0</version>
          <scope>provided</scope>
      </dependency>

      <!-- JSP API -->
      <!-- http://mvnrepository.com/artifact/javax.servlet.jsp/jsp-api -->
      <dependency>
          <groupId>javax.servlet.jsp</groupId>
          <artifactId>jsp-api</artifactId>
          <version>2.2</version>
          <scope>provided</scope>
      </dependency>

      <!-- MySQL JDBC driver -->
      <!-- http://mvnrepository.com/artifact/mysql/mysql-connector-java -->
      <dependency>
          <groupId>mysql</groupId>
          <artifactId>mysql-connector-java</artifactId>
          <version>5.1.34</version>
      </dependency>

      <!-- Oracle JDBC driver -->
      <dependency>
          <groupId>com.oracle</groupId>
          <artifactId>ojdbc6</artifactId>
          <version>11.2.0.3</version>
      </dependency>

      <!-- SQLServer JDBC driver (JTDS) -->
      <!-- http://mvnrepository.com/artifact/net.sourceforge.jtds/jtds -->
      <dependency>
          <groupId>net.sourceforge.jtds</groupId>
          <artifactId>jtds</artifactId>
          <version>1.3.1</version>
      </dependency>
    
    
  </dependencies>
 
  <build>
      <finalName>SpringMVCAnnotationSecurity</finalName>
      <plugins>
    
          <!-- Config: Maven Tomcat Plugin -->
          <!-- http://mvnrepository.com/artifact/org.apache.tomcat.maven/tomcat7-maven-plugin -->
          <plugin>
              <groupId>org.apache.tomcat.maven</groupId>
              <artifactId>tomcat7-maven-plugin</artifactId>
              <version>2.2</version>
              <!-- Config: contextPath and Port (Default: /SpringMVCAnnotationSecurity : 8080) -->
              <!--
              <configuration>
                  <path>/</path>
                  <port>8899</port>
              </configuration>
              -->   
          </plugin>
      </plugins>
  </build>       
 
</project>

5. Конфигурация Spring MVC & Security

SpringWebAppInitializer.java
package org.o7planning.springmvcsecurity.config;

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

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

public class SpringWebAppInitializer implements WebApplicationInitializer {

    @Override
    public void onStartup(ServletContext servletContext) throws ServletException {
        AnnotationConfigWebApplicationContext appContext = new AnnotationConfigWebApplicationContext();
        appContext.register(ApplicationContextConfig.class);

        ServletRegistration.Dynamic dispatcher = servletContext.addServlet("SpringDispatcher",
                new DispatcherServlet(appContext));
        dispatcher.setLoadOnStartup(1);
        dispatcher.addMapping("/");
    }

}
Класс ApplicationContextConfig исползованный для конфигурации содержания Spring MVC, включает:
  • DataSource
  • Transaction Manager
  • Beans
  • ...
ApplicationContextConfig.java
package org.o7planning.springmvcsecurity.config;

import javax.sql.DataSource;

import org.o7planning.springmvcsecurity.dao.UserInfoDAO;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import org.springframework.context.annotation.PropertySource;
import org.springframework.context.support.ResourceBundleMessageSource;
import org.springframework.core.env.Environment;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.jdbc.datasource.DriverManagerDataSource;
import org.springframework.transaction.annotation.EnableTransactionManagement;
import org.springframework.web.servlet.view.InternalResourceViewResolver;

@Configuration
@ComponentScan("org.o7planning.springmvcsecurity.*")
@EnableTransactionManagement
// Load to Environment.
@PropertySource("classpath:datasource-cfg.properties")
public class ApplicationContextConfig {

  // The Environment class serves as the property holder
  // and stores all the properties loaded by the @PropertySource
  @Autowired
  private Environment env;

  @Autowired
  private UserInfoDAO userInfoDAO;

  @Bean
  public ResourceBundleMessageSource messageSource() {
      ResourceBundleMessageSource rb = new ResourceBundleMessageSource();
      // Load property in message/validator.properties
      rb.setBasenames(new String[] { "messages/validator" });
      return rb;
  }

  @Bean(name = "viewResolver")
  public InternalResourceViewResolver getViewResolver() {
      InternalResourceViewResolver viewResolver = new InternalResourceViewResolver();
      viewResolver.setPrefix("/WEB-INF/pages/");
      viewResolver.setSuffix(".jsp");
      return viewResolver;
  }

  @Bean(name = "dataSource")
  public DataSource getDataSource() {
      DriverManagerDataSource dataSource = new DriverManagerDataSource();

      // See: datasouce-cfg.properties
      dataSource.setDriverClassName(env.getProperty("ds.database-driver"));
      dataSource.setUrl(env.getProperty("ds.url"));
      dataSource.setUsername(env.getProperty("ds.username"));
      dataSource.setPassword(env.getProperty("ds.password"));

      System.out.println("## getDataSource: " + dataSource);

      return dataSource;
  }

  // Transaction Manager
  @Autowired
  @Bean(name = "transactionManager")
  public DataSourceTransactionManager getTransactionManager(DataSource dataSource) {
      DataSourceTransactionManager transactionManager = new DataSourceTransactionManager(dataSource);

      return transactionManager;
  }

}
ApplicationContextConfig прочитает файл datasouce-cfg.xml:
datasouce-cfg.properties (For Oracle)
# DataSource

ds.database-driver=oracle.jdbc.driver.OracleDriver
ds.url=jdbc:oracle:thin:@localhost:1521:db12c
ds.username=test
ds.password=12345
datasource-cfg.properties (For SQL Server)
# DataSource

ds.database-driver=net.sourceforge.jtds.jdbc.Driver
ds.url=jdbc:jtds:sqlserver://localhost:1433/simplehr;instance=SQLEXPRESS
ds.username=test
ds.password=12345
datasource-cfg.properties (For MySQL)
# DataSource

ds.database-driver=com.mysql.jdbc.Driver
ds.url=jdbc:mysql://localhost:3306/mydatabase
ds.username=root
ds.password=12345
WebMvcConfig.java
package org.o7planning.springmvcsecurity.config;

import java.nio.charset.Charset;
import java.util.Arrays;
import java.util.List;

import org.springframework.context.annotation.Configuration;
import org.springframework.http.MediaType;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.converter.StringHttpMessageConverter;
import org.springframework.web.servlet.config.annotation.DefaultServletHandlerConfigurer;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;

@Configuration
@EnableWebMvc
public class WebMvcConfig extends WebMvcConfigurerAdapter {

   private static final Charset UTF8 = Charset.forName("UTF-8");

   // Config UTF-8 Encoding.
   @Override
   public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
       StringHttpMessageConverter stringConverter = new StringHttpMessageConverter();
       stringConverter.setSupportedMediaTypes(Arrays.asList(new MediaType("text", "plain", UTF8)));
       converters.add(stringConverter);

       // Add other converters ...
   }

   // Static Resource Config
   // equivalents for <mvc:resources/> tags
   @Override
   public void addResourceHandlers(ResourceHandlerRegistry registry) {
       registry.addResourceHandler("/css/**").addResourceLocations("/css/").setCachePeriod(31556926);
       registry.addResourceHandler("/img/**").addResourceLocations("/img/").setCachePeriod(31556926);
       registry.addResourceHandler("/js/**").addResourceLocations("/js/").setCachePeriod(31556926);
   }

   // Equivalent for <mvc:default-servlet-handler/> tag
   @Override
   public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
       configurer.enable();
   }

}
SpringSecurityInitializer.java
package org.o7planning.springmvcsecurity.config;

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


public class SpringSecurityInitializer extends AbstractSecurityWebApplicationInitializer {

   // Do nothing

}
WebSecurityConfig.java
package org.o7planning.springmvcsecurity.config;

import org.o7planning.springmvcsecurity.authentication.MyDBAuthenticationService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;

@Configuration
// @EnableWebSecurity = @EnableWebMVCSecurity + Extra features
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {

   
    @Autowired
    MyDBAuthenticationService myDBAauthenticationService;

    @Autowired
    public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {

        // Users in memory.

        auth.inMemoryAuthentication().withUser("user1").password("12345").roles("USER");
        auth.inMemoryAuthentication().withUser("admin1").password("12345").roles("USER, ADMIN");

        // For User in database.
        auth.userDetailsService(myDBAauthenticationService);

    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {

        http.csrf().disable();

        // The pages does not require login
        http.authorizeRequests().antMatchers("/", "/welcome", "/login", "/logout").permitAll();

        // /userInfo page requires login as USER or ADMIN.
        // If no login, it will redirect to /login page.
        http.authorizeRequests().antMatchers("/userInfo").access("hasAnyRole('ROLE_USER', 'ROLE_ADMIN')");

        // For ADMIN only.
        http.authorizeRequests().antMatchers("/admin").access("hasRole('ROLE_ADMIN')");

        // When the user has logged in as XX.
        // But access a page that requires role YY,
        // AccessDeniedException will throw.
        http.authorizeRequests().and().exceptionHandling().accessDeniedPage("/403");

        // Config for Login Form
        http.authorizeRequests().and().formLogin()//
                // Submit URL of login page.
                .loginProcessingUrl("/j_spring_security_check") // Submit URL
                .loginPage("/login")//
                .defaultSuccessUrl("/userInfo")//
                .failureUrl("/login?error=true")//
                .usernameParameter("username")//
                .passwordParameter("password")
                // Config for Logout Page
                .and().logout().logoutUrl("/logout").logoutSuccessUrl("/logoutSuccessful");

    }
}

6. Классы учатсвующие в безопасности (Security)

Класс UserInfo соответствует таблице USERS в базе данных.
UserInfo.java
package org.o7planning.springmvcsecurity.model;

public class UserInfo {

    private String userName;
    private String password;
    
    public UserInfo()  {
        
    }

    public UserInfo(String userName, String password) {
        this.userName = userName;
        this.password = password;
    }

    public String getUserName() {
        return userName;
    }

    public void setUserName(String userName) {
        this.userName = userName;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

}
Класс UserInfoMapper используется для сопоставления столбцов вв команде SQL соответственно с полями (field) класса UserInfo.
UserInfoMapper.java
package org.o7planning.springmvcsecurity.mapper;

import java.sql.ResultSet;
import java.sql.SQLException;

import org.o7planning.springmvcsecurity.model.UserInfo;
import org.springframework.jdbc.core.RowMapper;

public class UserInfoMapper implements RowMapper<UserInfo> {

    @Override
    public UserInfo mapRow(ResultSet rs, int rowNum) throws SQLException {

        String userName = rs.getString("Username");
        String password = rs.getString("Password");

        return new UserInfo(userName, password);
    }

}
UserInfoDAO.java
package org.o7planning.springmvcsecurity.dao;

import java.util.List;

import org.o7planning.springmvcsecurity.model.UserInfo;

public interface UserInfoDAO {
    
    public UserInfo findUserInfo(String userName);
    
    // [USER,AMIN,..]
    public List<String> getUserRoles(String userName);
    
}
UserInfoDAOImpl.java
package org.o7planning.springmvcsecurity.dao.impl;

import java.util.List;

import javax.sql.DataSource;

import org.o7planning.springmvcsecurity.dao.UserInfoDAO;
import org.o7planning.springmvcsecurity.mapper.UserInfoMapper;
import org.o7planning.springmvcsecurity.model.UserInfo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.EmptyResultDataAccessException;
import org.springframework.jdbc.core.support.JdbcDaoSupport;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

@Service
@Transactional
public class UserInfoDAOImpl extends JdbcDaoSupport implements UserInfoDAO {

    @Autowired
    public UserInfoDAOImpl(DataSource dataSource) {
        this.setDataSource(dataSource);
    }
 

    @Override
    public UserInfo findUserInfo(String userName) {
        String sql = "Select u.Username,u.Password "//
                + " from Users u where u.Username = ? ";

        Object[] params = new Object[] { userName };
        UserInfoMapper mapper = new UserInfoMapper();
        try {
            UserInfo userInfo = this.getJdbcTemplate().queryForObject(sql, params, mapper);
            return userInfo;
        } catch (EmptyResultDataAccessException e) {
            return null;
        }
    }


    @Override
    public List<String> getUserRoles(String userName) {
        String sql = "Select r.User_Role "//
                + " from User_Roles r where r.Username = ? ";
        
        Object[] params = new Object[] { userName };
        
        List<String> roles = this.getJdbcTemplate().queryForList(sql,params, String.class);
        
        return roles;
    }
    
}
Класс MyDBAuthenticationService используется для кастомизирования аутентификации, он выполняет interface AuthenticationService.
MyDBAuthenticationService.java
package org.o7planning.springmvcsecurity.authentication;

import java.util.ArrayList;
import java.util.List;

import org.o7planning.springmvcsecurity.dao.UserInfoDAO;
import org.o7planning.springmvcsecurity.model.UserInfo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service;

@Service
public class MyDBAuthenticationService implements UserDetailsService {

    @Autowired
    private UserInfoDAO userInfoDAO;

    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        UserInfo userInfo = userInfoDAO.findUserInfo(username);
        System.out.println("UserInfo= " + userInfo);

        if (userInfo == null) {
            throw new UsernameNotFoundException("User " + username + " was not found in the database");
        }
        
        // [USER,ADMIN,..]
        List<String> roles= userInfoDAO.getUserRoles(username);
        
        List<GrantedAuthority> grantList= new ArrayList<GrantedAuthority>();
        if(roles!= null)  {
            for(String role: roles)  {
                // ROLE_USER, ROLE_ADMIN,..
                GrantedAuthority authority = new SimpleGrantedAuthority("ROLE_" + role);
                grantList.add(authority);
            }
        }        
        
        UserDetails userDetails = (UserDetails) new User(userInfo.getUserName(), //
                userInfo.getPassword(),grantList);

        return userDetails;
    }
    
}

7. Spring MVC Controller

MainController.java
package org.o7planning.springmvcsecurity.controller;

import java.security.Principal;

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

@Controller
public class MainController {

   @RequestMapping(value = { "/", "/welcome" }, method = RequestMethod.GET)
   public String welcomePage(Model model) {
       model.addAttribute("title", "Welcome");
       model.addAttribute("message", "This is welcome page!");
       return "welcomePage";
   }

   @RequestMapping(value = "/admin", method = RequestMethod.GET)
   public String adminPage(Model model) {
       return "adminPage";
   }

   @RequestMapping(value = "/login", method = RequestMethod.GET)
   public String loginPage(Model model ) {
     
       return "loginPage";
   }

   @RequestMapping(value = "/logoutSuccessful", method = RequestMethod.GET)
   public String logoutSuccessfulPage(Model model) {
       model.addAttribute("title", "Logout");
       return "logoutSuccessfulPage";
   }

   @RequestMapping(value = "/userInfo", method = RequestMethod.GET)
   public String userInfo(Model model, Principal principal) {

       // After user login successfully.
       String userName = principal.getName();

       System.out.println("User Name: "+ userName);

       return "userInfoPage";
   }

   @RequestMapping(value = "/403", method = RequestMethod.GET)
   public String accessDenied(Model model, Principal principal) {
       
       if (principal != null) {
           model.addAttribute("message", "Hi " + principal.getName()
                   + "<br> You do not have permission to access this page!");
       } else {
           model.addAttribute("msg",
                   "You do not have permission to access this page!");
       }
       return "403Page";
   }
}

8. JSP Pages

_menu.jsp
<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>

<div style="border: 1px solid #ccc;padding:5px;margin-bottom:20px;">

  <a href="${pageContext.request.contextPath}/welcome">Home</a>

  | &nbsp;
 
   <a href="${pageContext.request.contextPath}/userInfo">User Info</a>
 
  | &nbsp;
 
  <a href="${pageContext.request.contextPath}/admin">Admin</a>
 
  <c:if test="${pageContext.request.userPrincipal.name != null}">
 
     | &nbsp;
     <a href="${pageContext.request.contextPath}/logout">Logout</a>
    
  </c:if>
 
</div>
403Page.jsp
<%@page session="false"%>
<html>
<head>
<title>Access Denied</title>
</head>
<body>
<jsp:include page="_menu.jsp"/>

    <h3 style="color:red;">${message}</h3>
</body>
</html>
adminPage.jsp
<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<%@page session="true"%>

<html>
<head>
<title>${title}</title>
</head>
<body>
    <jsp:include page="_menu.jsp" />

    <h2>Admin Page</h2>


    <h3>Welcome : ${pageContext.request.userPrincipal.name}</h3>

    <b>This is protected page!</b>  
</body>
</html>
loginPage.jsp
<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>

<html>
<head><title>Login</title></head>
<body>
   <jsp:include page="_menu.jsp" />
   
   
   <h1>Login</h1>
    
     <!-- /login?error=true -->
     <c:if test="${param.error == 'true'}">
         <div style="color:red;margin:10px 0px;">
         
                Login Failed!!!<br />
                Reason :  ${sessionScope["SPRING_SECURITY_LAST_EXCEPTION"].message}
                
         </div>
    </c:if>
      
   <h3>Enter user name and password:</h3>  
    
   <form name='f' action="${pageContext.request.contextPath}/j_spring_security_check" method='POST'>
      <table>
         <tr>
            <td>User:</td>
            <td><input type='text' name='username' value=''></td>
         </tr>
         <tr>
            <td>Password:</td>
            <td><input type='password' name='password' /></td>
         </tr>
         <tr>
            <td><input name="submit" type="submit" value="submit" /></td>
         </tr>
      </table>
  </form>
</body>
</html>
logoutSuccessfulPage.jsp
<html>
<head>
<title>Logout</title>
</head>
<body>
    <jsp:include page="_menu.jsp" />

    <h1>Logout Successful!</h1>
</body>
</html>
userInfoPage.jsp
<%@page session="false"%>
<html>
<head>
<title>${title}</title>
</head>
<body>
    <jsp:include page="_menu.jsp" />


    <h1>Message : ${message}</h1>
</body>
</html>
welcomePage.jsp
<%@page session="false"%>
<html>
<head>
<title>${title}</title>
</head>
<body>
  <h1>Message : ${message}</h1>
</body>
</html>

9. Конфигурация и запуск приложения

В первый раз, перед запуском приложения вам нужно build (построить) полностью project.
Нажмите на правую кнопку мыши на project, выберите:
  • Run As/Maven install
Конфигурируйте для запуска приложения:
Введите:
  • Name: Run SpringMVCSecurity
  • Base directory: ${workspace_loc:/SpringMVCAnnotationSecurity}
  • Goals: tomcat7:run
Запуск URL:
Введите ссылку для просмотра информации user, в случае если вы еще не вошли в систему (login), website перенаправит к странице login.
Если вы ввели неправильную информацию и нажали на Submit. Website еще раз перенаправит на страницу login.
В случае, когда вы успешно вошли в систему:
Вы можете попробовать с ссылкой.
Ссылка выше только позволяет user с ролью ADMIN (ROLE_ADMIN) получить доступ:

В случае если вы еще не вошли в систему (login), website перенаправит на страницу login, если вы вошли с ролью ROLE_USER вы получите оповещение запрет доступа (Access Denied)

10. Fix Error!

Примечание, если вы получили ошибку:
HTTP Status 404 - /SpringMVCAnnotationSecurity/j_spring_security_check
Гарантируйте что в вашем приложении уже существует класс SpringSecurityInitializer:
SpringSecurityInitializer.java
package org.o7planning.springmvcsecurity.config;

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


public class SpringSecurityInitializer extends AbstractSecurityWebApplicationInitializer {

    // Do nothing

}