LoginSignup
1
1

More than 3 years have passed since last update.

カスタムしたログインページを表示、DBのユーザでログインする

Posted at

sidebar.htmlが読み込まれていない原因

 SecurityConfig.javaのセキュリティ設定を無視(ignoring)するパスの指定する際の構文が誤っていたためsidebar.htmlが読み込まれていなかったそのためログイン後の画面が表示されない

誤り

    @Override
    public void configure(WebSecurity web) throws Exception{
        web.ignoring().antMatchers("css/***,*/webjars/***");
    }

修正


    @Override
    public void configure(WebSecurity web) throws Exception{
        web.ignoring().antMatchers("css/***","/webjars/***");
    }

結果

1.ログイン後の画面の確認
 ブラウザでhttp/localhost:8080/にアクセス後表示された画面でユーザ名「user」
 パスワード「password」を入力しログイン後の画面を確認

image.png

image.png

***2.Remember Meの機能が正しく機能しているか確認

2-1ログイン画面でユーザ名とパスワード入力後「ログインしたままにする」にチェックをつけてログインする。
image.png

image.png

2-2 ブラウザをいったん閉じ再度http:loclahost:8080/にアクセスしログイン後の画面が表示されていることを確認
image.png

image.png

DBのユーザでログインする。

以下のことを実施します。
※カスタムしたログインページを表示のプログラムを使用します。
 ・DBにユーザを登録する
 ・DBのユーザでログイン

ユーティリティの作成

・列挙型を作成

Role.java
package com.example.demo.util;

public enum Role {
    ADMIN,USER
}

・クラス型を作成

 Collections.unmodifiableMap()はMAPを定数として利用が可能

Type.java
package com.example.demo.util;

import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.Map;
public class Type {

    public static final Map<Integer,String>GENDERS;
    static {
        Map<Integer,String>genders = new LinkedHashMap<>();
        genders.put(0, "選択しない");
        genders.put(1, "男性");
        genders.put(2,"女性");
        genders.put(3, "その他");
        GENDERS = Collections.unmodifiableMap(genders);
    }


}

モデルの作成

package com.example.demo.model;

import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.validation.constraints.Email;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.Size;

import lombok.Getter;
import lombok.Setter;

@Getter
@Setter
@Entity

public class SiteUser {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @Size(min = 2, max = 20)
    private String username;
    @Size(min =4,max = 255)
    private String password;

    @NotBlank
    @Email
    private String email;

    private int gender;
    private boolean admin;
    private String role;
    private boolean active = true;
}

H2 Databaseの設定

 application.propertiesを編集
 

 spring.datasource.url=jdbc:h2:./textdb
 spring.jpa.hibernate.ddl-auto=update

 spring.datasource.url=jdbc:h2:保存先
  DBをローカルに保存
 Spring.jpa.hibernate.ddl-auto=update
  @Entityのテーブルがない場合、作成する。
   (Spring Bootアプリケーションを終了してもテーブルは削除されない)

リポジトリ

package com.example.demo.repository;

import org.springframework.data.jpa.repository.JpaRepository;
import com.example.demo.model.SiteUser;


public interface SiteUserRepository extends JpaRepository<SiteUser,Long> {

    SiteUser findByUsername(String username);
    boolean existsByUsername(String username);
}

サービスを作成

Spring Securityはユーザデータを扱うためにインターフェースを認証に利用する。

 @Service
  クラスがサービスそうであることを示す。
  UserDetailsServiceインターフェースはユーザを特定するために使用される。
  このインターフェースには実装が必要なloadUserByUsername()というメソッドがある。

package com.example.demo.service;

import java.util.HashSet;
import java.util.Set;

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;

import com.example.demo.model.SiteUser;
import com.example.demo.repository.SiteUserRepository;
import lombok.RequiredArgsConstructor;


@RequiredArgsConstructor
@Service

public class UserDetailsServiceImpl implements UserDetailsService{

    private final SiteUserRepository userRepository;

    @Override
    public UserDetails loadUserByUsername(String username)
        throws UsernameNotFoundException{
        SiteUser user = userRepository.findByUsername(username);
        if(user == null) {
            throw new UsernameNotFoundException(username + "not found");
        }
        return createUserDetails(user);
    }

    public User createUserDetails(SiteUser user) {
        Set<GrantedAuthority> grantedAuthories = new HashSet<>();
        grantedAuthories.add(
                new SimpleGrantedAuthority("ROLE_" + user.getRole()));

        return new User(user.getUsername(),user.getPassword(),grantedAuthories);

    }


}

SecurityConfigとSecurityControllerの編集

package com.example.demo.config;

import org.springframework.context.annotation.Bean;
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.builders.WebSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
import com.example.demo.util.Role;
import lombok.RequiredArgsConstructor;

@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter{
    @Bean
    public BCryptPasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }
    @Override
    public void configure(WebSecurity web) throws Exception{
        web.ignoring().antMatchers("/js/**","css/***","/webjars/***");
    }
    @Override
    protected void configure(HttpSecurity http) throws Exception{
        http.authorizeRequests().antMatchers("/login","/register").permitAll()
        .antMatchers("/admin/**").hasRole(Role.ADMIN.name())
        .anyRequest().authenticated().and()
        .formLogin().loginPage("/login").defaultSuccessUrl("/").and()
        .logout().logoutRequestMatcher(new AntPathRequestMatcher("/logout")).and()
        .rememberMe();
    }
    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception{
        auth.userDetailsService(userDetailsService).passwordEncoder(passwordEncoder());
    }
}

SecurityController.java

package com.example.demo.controller;

import org.springframework.security.core.Authentication;

import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;

import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.validation.BindingResult;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PostMapping;

import com.example.demo.model.SiteUser;
import com.example.demo.repository.SiteUserRepository;
import com.example.demo.util.Role;

import lombok.RequiredArgsConstructor;

@RequiredArgsConstructor
@Controller
public class SecurityController {

    @GetMapping("/login")
    public String login() {
        return "login";
    }
    @GetMapping("/")
    public String showList(Authentication loginUser,Model model) {
        model.addAttribute("username",loginUser.getName());
        model.addAttribute("role",loginUser.getAuthorities());
        return"user";
    }

    @GetMapping("/admin/list")
    public String showAdminList(Authentication loginUser,Model model) {
        model.addAttribute("users",userRepository.findAll());
        return "user";

    }
    @GetMapping("/register")
    public String register(@ModelAttribute("user") SiteUser user) {
        return "register";
    }

    @PostMapping("/register")
    public String process(@Validated @ModelAttribute("user") SiteUser user,BindingResult reult) {

        if(result.hasErrors()) {
            return "register";
        }else {
            user.setRole(Role.USER.name());
        }
        userRepository.seve(user);
        return"redirect:/login?register";
    }
}

pom.xml編集

 thymeleaf-extras-springsecurity5
  ThymeleafとSpring Security の結合モジュール
  Thymeleafで、現在のユーザ権限などを取得できる
 datatables-buttons、datatables-plugins、jszip
  DataTablesのボタン出力、日本語化で必要なモジュール

<dependency>
    <groupId>org.thymeleaf.extras</groupId>
  <artifactId>thymeleaf-extras-springsecurity5</artifactId>
</dependency>
<dependency>
    <groupId>org.webjars</groupId>
    <artifactId>datatables-buttons</artifactId>
    <version>1.6.1</version>
</dependency>
<dependency>
    <groupId>org.webjars</groupId>
    <artifactId>datatables-plugins</artifactId>
    <version>1.10.20</version>
</dependency>
<dependency>
    <groupId>org.webjars</groupId>
    <artifactId>jszip</artifactId>
    <version>3.1.0</version>
</dependency>

thymeleafテンプレートを作成

login.htmlを編集

<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<th:block th:insert="fragments/base :: header"></th:block>
</head>
<body class="bg-gradient-primary">
    <div class="container">
    <div class="row justify-content-center">
        <div class="col-xl-10 col-lg-12 col-md-9">
        <div class="card o-hidden border-0 shadow-lg my-5">
        <div class="card-body p-0">
        <div class="row">
        <div class="col-lg-6 d-none d-lg-block bg-login-image"></div>
        <div class="col-lg-6">
        <div class="p-5">
        <div class="text-center">
            <h1 class="h4 text-gray-900 mb-4">ユーザ管理システム</h1>
        </div>
        <div class="alert alert-danger" th:if="${param.error}">
            <small>ユーザ名またはパスワードが正しくありません。</small>
        </div>
        <div class="alert alert-success" th:if="${param.register}">
            <small>ユーザを新規登録しました</small>
        </div>
        <div class="alert alert-success" th:if="${param.logout}">
            <small>ログアウトしました</small>
        </div>
        <form th:action="@{/login}" class="user" method="post">
            <div class="form-group">
                <input type="text"class="form-control form-control-user" name="username"placeholder="ユーザ名">
            </div>
            <div class="form-group">
                <input type="password" class="form-control form-control-user" name="password" placeholder="パスワード">
            </div>
            <div class="form-group">
                <div class="custom-control custom-checkbox small">
                <input type="checkbox" class="custom-control-input"id="remember-me"name="remember-me">
                <label class="custom-control-label"for="remember-me">ログインしたままにする</label>
                </div>
            </div>
            <button class="btn btn-primary btn-user btn-block">ログイン</button>
            <div class="text-center">
                <a th:href="@{/register}">新規登録はこちら</a>
            </div>
        </form>
        <hr>
        </div>
        </div>
        </div>
        </div>
        </div>
        </div>
    </div>
    </div>
    <th:block th:insert="fragments/base :: scripts"></th:block>
</body>
</html>

以上

1
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1