データベースを使用したSpring Securityフォームのログイン

データベースを使用したSpring Securityフォームのログイン

このチュートリアルでは、Spring Securityでデータベース認証(XMLと注釈の両方を使用)を実行する方法を示します。

使用される技術:

  1. Spring 3.2.8.RELEASE

  2. Spring Security 3.2.3.RELEASE

  3. Spring JDBC 3.2.3.RELEASE

  4. Eclipse 4.2

  5. JDK 1.6

  6. メーベン3

  7. Tomcat 6または7(サーブレット3.x)

  8. MySQLサーバー5.6

以前のlogin-form in-memory authenticationは再利用され、次の機能をサポートするように拡張されます。

  1. Spring-JDBCおよびMySQLを使用したデータベース認証。

  2. Spring Security、JSP TagLib、sec:authorize access="hasRole('ROLE_USER')

  3. 403アクセス拒否ページをカスタマイズします。

1. プロジェクトのデモ

2. プロジェクトディレクトリ

最終的なプロジェクト構造(XMLベース)を確認します。

spring-security-database-xml-directory

最終的なプロジェクト構造を確認します(注釈ベース):

spring-security-database-annotation-directory

3. プロジェクトの依存関係

Spring、Spring Security、JDBC、Taglib、MySQLの依存関係を取得します

pom.xml

    
        1.6
        3.2.8.RELEASE
        3.2.3.RELEASE
        1.2
        5.1.30
    

    

        
        
            org.springframework
            spring-core
            ${spring.version}
        

        
            org.springframework
            spring-web
            ${spring.version}
        

        
            org.springframework
            spring-webmvc
            ${spring.version}
        

        
            org.springframework
            spring-jdbc
            ${spring.version}
        

        
        
            org.springframework.security
            spring-security-web
            ${spring.security.version}
        

        
            org.springframework.security
            spring-security-config
            ${spring.security.version}
        

        
        
            org.springframework.security
            spring-security-taglibs
            ${spring.security.version}
        

        
        
            jstl
            jstl
            ${jstl.version}
        

                
        
            mysql
            mysql-connector-java
            ${mysql.connector.version}
        

    

4. データベース

データベース認証を実行するには、ユーザーとロールの詳細を保存するテーブルを作成する必要があります。 このSpring Security user-schema referenceを参照してください。 usersおよびuser_rolesテーブルを作成するためのMySQLスクリプトは次のとおりです。

4.1 Create a “users” table.

users.sql

CREATE  TABLE users (
  username VARCHAR(45) NOT NULL ,
  password VARCHAR(45) NOT NULL ,
  enabled TINYINT NOT NULL DEFAULT 1 ,
  PRIMARY KEY (username));

4.2 Create a “user_roles” table.

user_roles.sql

CREATE TABLE user_roles (
  user_role_id int(11) NOT NULL AUTO_INCREMENT,
  username varchar(45) NOT NULL,
  role varchar(45) NOT NULL,
  PRIMARY KEY (user_role_id),
  UNIQUE KEY uni_username_role (role,username),
  KEY fk_username_idx (username),
  CONSTRAINT fk_username FOREIGN KEY (username) REFERENCES users (username));

4.3 Inserts some records for testing.

INSERT INTO users(username,password,enabled)
VALUES ('example','123456', true);
INSERT INTO users(username,password,enabled)
VALUES ('alex','123456', true);

INSERT INTO user_roles (username, role)
VALUES ('example', 'ROLE_USER');
INSERT INTO user_roles (username, role)
VALUES ('example', 'ROLE_ADMIN');
INSERT INTO user_roles (username, role)
VALUES ('alex', 'ROLE_USER');

Note

  1. ユーザー名「example」、role_userおよびrole_admin。

  2. ユーザー名「alexa」、role_user。

5. Spring Securityの構成

XMLと注釈の両方のSpring Security。

5.1 Create a DataSource to connect MySQL.

spring-database.xml



    

        
        
        
        
    

Springアノテーションに相当するもの:

SecurityConfig.java

package com.example.config;

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.jdbc.datasource.DriverManagerDataSource;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.view.InternalResourceViewResolver;
import org.springframework.web.servlet.view.JstlView;

@EnableWebMvc
@Configuration
@ComponentScan({ "com.example.web.*" })
@Import({ SecurityConfig.class })
public class AppConfig {

    @Bean(name = "dataSource")
    public DriverManagerDataSource dataSource() {
        DriverManagerDataSource driverManagerDataSource = new DriverManagerDataSource();
        driverManagerDataSource.setDriverClassName("com.mysql.jdbc.Driver");
        driverManagerDataSource.setUrl("jdbc:mysql://localhost:3306/test");
        driverManagerDataSource.setUsername("root");
        driverManagerDataSource.setPassword("password");
        return driverManagerDataSource;
    }

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

}

5.2 Use jdbc-user-service to define a query to perform database authentication.

spring-security.xml



    
    

        

        
        

        
        
        
        
    

    
    
      
        
      
    

Spring Securityアノテーションに相当するもの:

SecurityConfig.java

package com.example.config;

import javax.sql.DataSource;
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
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Autowired
    DataSource dataSource;

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

      auth.jdbcAuthentication().dataSource(dataSource)
        .usersByUsernameQuery(
            "select username,password, enabled from users where username=?")
        .authoritiesByUsernameQuery(
            "select username, role from user_roles where username=?");
    }

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

      http.authorizeRequests()
        .antMatchers("/admin/**").access("hasRole('ROLE_ADMIN')")
        .and()
          .formLogin().loginPage("/login").failureUrl("/login?error")
          .usernameParameter("username").passwordParameter("password")
        .and()
          .logout().logoutSuccessUrl("/login?logout")
        .and()
          .exceptionHandling().accessDeniedPage("/403")
        .and()
          .csrf();
    }
}

6. JSPページ

カスタムログインページのJSPページ。

6.1 Default page, show the use of Spring Security JSP taglib sec:authorize to display content to users who have “ROLE_USER” authority.

hello.jsp

<%@taglib prefix="sec"
    uri="http://www.springframework.org/security/tags"%>
<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>


    

Title : ${title}

Message : ${message}

User : ${pageContext.request.userPrincipal.name} | Logout

6.2 Page to display the custom login form.

login.jsp

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


Login Page




    

Spring Security Login Form (Database Authentication)

Login with Username and Password

${error}
${msg}
User:
Password:

6.3 This page is password protected, only authenticated user “ROLE_ADMIN” is allowed to access.

admin.jsp

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


    

Title : ${title}

Message : ${message}

Welcome : ${pageContext.request.userPrincipal.name} | Logout

6.4 Custom 403 access denied page.

403.jsp

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


    

HTTP Status 403 - Access is denied

You do not have permission to access this page!

Username : ${username}
You do not have permission to access this page!

7. Spring MVCコントローラー

シンプルなコントローラー。

MainController.java

package com.example.web.controller;

import org.springframework.security.authentication.AnonymousAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.servlet.ModelAndView;

@Controller
public class MainController {

    @RequestMapping(value = { "/", "/welcome**" }, method = RequestMethod.GET)
    public ModelAndView defaultPage() {

      ModelAndView model = new ModelAndView();
      model.addObject("title", "Spring Security Login Form - Database Authentication");
      model.addObject("message", "This is default page!");
      model.setViewName("hello");
      return model;

    }

    @RequestMapping(value = "/admin**", method = RequestMethod.GET)
    public ModelAndView adminPage() {

      ModelAndView model = new ModelAndView();
      model.addObject("title", "Spring Security Login Form - Database Authentication");
      model.addObject("message", "This page is for ROLE_ADMIN only!");
      model.setViewName("admin");
      return model;

    }

    @RequestMapping(value = "/login", method = RequestMethod.GET)
    public ModelAndView login(@RequestParam(value = "error", required = false) String error,
        @RequestParam(value = "logout", required = false) String logout) {

      ModelAndView model = new ModelAndView();
      if (error != null) {
        model.addObject("error", "Invalid username and password!");
      }

      if (logout != null) {
        model.addObject("msg", "You've been logged out successfully.");
      }
      model.setViewName("login");

      return model;

    }

    //for 403 access denied page
    @RequestMapping(value = "/403", method = RequestMethod.GET)
    public ModelAndView accesssDenied() {

      ModelAndView model = new ModelAndView();

      //check if user is login
      Authentication auth = SecurityContextHolder.getContext().getAuthentication();
      if (!(auth instanceof AnonymousAuthenticationToken)) {
        UserDetails userDetail = (UserDetails) auth.getPrincipal();
        model.addObject("username", userDetail.getUsername());
      }

      model.setViewName("403");
      return model;

    }

}

8. Demo

spring-security-database-default

8.2 Try to access /admin page, only “example” ROLE_ADMIN is allowed to access.

spring-security-database-admin

8.3. 「alex」が/adminにアクセスしようとすると、403アクセス拒否ページが表示されます。

spring-security-database-403

8.3 “alex” in default page, show the use of sec:authorize

spring-security-database-sec-tag

8.4. 「例」が/adminにアクセスしようとすると、管理ページが表示されます。

spring-security-database-admin-login

ソースコードをダウンロード

XMLバージョンのダウンロード–spring-security-login-form-database-xml.zip(16 KB)

注釈バージョンのダウンロード–spring-security-login-form-database-annotation.zip(22 KB)