1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

Spring SecurityのUserDetailsの挙動を確認する

Posted at

Spring Securityで認証によく使うUserDetailsについて

Spring Bootで認証を実装しようとしたとき、よく使うSpring側ですでに用意されているクラスと言えばUserUserDetailsおよびUserDetailsServiceだと思いますが、至極当たり前のことながら意外とこれらの挙動を正しく理解していなかったので、改めて確認してみました。

実装

まず、ユーザ情報はデータベースから取得するので、取得用のEntityを実装します。

LoginUser.java
import java.util.Date;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;

import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;

@Data
@Entity
@NoArgsConstructor
@AllArgsConstructor
@Builder
@Table(name="m_user")
public class LoginUser{

    @Id
    @GeneratedValue(strategy=GenerationType.TABLE)
    @Column(name = "user_id")
    @Getter
    @Setter
    private String userId;

    @Column(name = "user_name")
    @Getter
    @Setter
    private String userName;

    @Column(name = "password")
    @Getter
    @Setter
    private String password;

    @Column(name = "pass_update_date")
    @Getter
    @Setter
    private Date passUpdateDate;

    @Column(name = "login_miss_times")
    @Getter
    @Setter
    private int loginMissTimes;

    @Column(name = "unlock")
    @Getter
    @Setter
    private boolean unlock;

    @Column(name = "enabled")
    @Getter
    @Setter
    private boolean enabled;

    @Column(name = "user_due_date")
    @Getter
    @Setter
    private Date userDueDate;

    @Column(name = "role_id")
    @Getter
    @Setter
    private String roleId;

}

肝心のUserDetailsです。

UserDetailsImpl.java
import java.util.Collection;
import java.util.Date;

import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;

import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;

@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder
public class UserDetailsImpl implements UserDetails {

	private LoginUser user;

	public UserDetailsImpl(LoginUser user) {
		this.user = user;
	}

    private Collection<? extends GrantedAuthority> authority;


    @Override
    public Collection<? extends GrantedAuthority> getAuthorities() {
        return authority;
    }

    @Override
    public String getPassword() {
        return user.getPassword();
    }

    @Override
    public String getUsername() {
        return user.getUserId();
    }

    

    @Override
    public boolean isAccountNonExpired() {

        if(user.getUserDueDate().after(new Date())) {
            
            return true;

        } else {

            return false;
        }
    }

    @Override
    public boolean isAccountNonLocked() {
        return user.isUnlock();
    }

    @Override
    public boolean isCredentialsNonExpired() {

        if(user.getPassUpdateDate().after(new Date())) {

            return true;

        } else {

            return false;

        }
    }

    @Override
    public boolean isEnabled() {
        return user.isEnabled();
    }
}

ユーザ情報のテーブル:

select * from m_user;
 user_id |                           password                           |  pass_update_date   | login_miss_times | unlock | role_id |   user_name    | enabled |    user_due_date    
---------+--------------------------------------------------------------+---------------------+------------------+--------+---------+----------------+---------+---------------------
 system  | $2a$10$xRTXvpMWly0oGiu65WZlm.3YL95LGVV2ASFjDhe6WF4.Qji1huIPa | 2099-12-31 23:59:59 |                0 | t      | admin   | システム管理者 | t       | 2099-12-31 23:59:59
 user    | $2a$10$xRTXvpMWly0oGiu65WZlm.3YL95LGVV2ASFjDhe6WF4.Qji1huIPa | 2099-12-31 23:59:59 |                0 | t      | general | 一般ユーザー   | t       | 2099-12-31 23:59:59
 sample1 | $2a$10$xRTXvpMWly0oGiu65WZlm.3YL95LGVV2ASFjDhe6WF4.Qji1huIPa | 1999-12-31 23:59:59 |                0 | t      | general | ユーザー1      | t       | 2099-12-31 23:59:59
 sample2 | $2a$10$xRTXvpMWly0oGiu65WZlm.3YL95LGVV2ASFjDhe6WF4.Qji1huIPa | 2099-12-31 23:59:59 |                0 | f      | general | ユーザー2      | t       | 2099-12-31 23:59:59
 sample3 | $2a$10$xRTXvpMWly0oGiu65WZlm.3YL95LGVV2ASFjDhe6WF4.Qji1huIPa | 2099-12-31 23:59:59 |                0 | t      | general | ユーザー3      | f       | 2099-12-31 23:59:59
 sample4 | $2a$10$xRTXvpMWly0oGiu65WZlm.3YL95LGVV2ASFjDhe6WF4.Qji1huIPa | 2099-12-31 23:59:59 |                0 | t      | general | ユーザー4      | t       | 1999-12-31 23:59:59

この実装内容で認証した際に、有効なアカウントとして認識されるのは、systemuserのみです。

というのも、UserDetailsを実装したクラスでは、isEnabledisUnlockedisAccountNonLockedなどのメソッドをオーバーライドしており、ここでfalseがひとつでも返ってきた場合は401Unauthorizedのメッセージが返ってきて、はじかれるようになっています。

オーバーライドしている内容を見れば明らかなのですが、最終的な挙動を正しく理解していなかったので、地味に悩みました。

1
0
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
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?