Spring Boot Outh 2認証サーバアプリケーション-5
今回は、DBで会員情報を検索して登録してみます.
まずメンバーエンティティを作成する必要があります.
セキュリティには必要な情報が含まれている必要がありますので、UserDetailsを継承し、関連フィールドを超えてください.
JPAを使用してRepositoryを作成します.
次に、MemberServiceとMemberServiceImplを作成します.
PasswordEncoderを使用するので、パスワードはenocde形式で挿入されます.
UserDetailsのloadUserByUserNameメソッドを上書きします.
認証プロバイダを追加して、後続のログイン情報を検証します.
すべての設定が完了し、先ほど作成したユーザー情報でトークンを受信します.
http://localhost:1995/oauth/authorize?client_id=foo&redirect_uri=http://localhost:1995/oauth2/callback&response_type=code&scope=read
接続後に作成したユーザー情報を使用してログインすると、トークンが発行されていれば成功します.
まずメンバーエンティティを作成する必要があります.
Member.java
@Builder
@Entity
@Getter
@NoArgsConstructor
@AllArgsConstructor
@Table(name = "MEMBER")
public class Member implements UserDetails {
@Id
@Column(name="USER_ID")
private String userId;
@Column(name="USER_PWD")
private String userPwd;
@Column(name="USER_NM")
private String userNm;
private String gender;
private Integer height;
private Integer weight;
@Column(name="PRIVATE_YN")
private String privateYn;
private Instant regdate;
@ElementCollection(fetch = FetchType.EAGER)
@Builder.Default
private List<String> roles = new ArrayList<>();
@Override
public Collection<? extends GrantedAuthority> getAuthorities() {
return this.roles.stream().map(SimpleGrantedAuthority::new).collect(Collectors.toList());
}
@JsonProperty(access = JsonProperty.Access.WRITE_ONLY)
@Override
public String getUsername() {
return this.userId;
}
@JsonProperty(access = JsonProperty.Access.WRITE_ONLY)
@Override
public String getPassword() {
return this.userPwd;
}
@JsonProperty(access = JsonProperty.Access.WRITE_ONLY)
@Override
public boolean isAccountNonExpired() {
return true;
}
@JsonProperty(access = JsonProperty.Access.WRITE_ONLY)
@Override
public boolean isAccountNonLocked() {
return true;
}
@JsonProperty(access = JsonProperty.Access.WRITE_ONLY)
@Override
public boolean isCredentialsNonExpired() {
return true;
}
@JsonProperty(access = JsonProperty.Access.WRITE_ONLY)
@Override
public boolean isEnabled() {
return true;
}
}
私が作っているTOYプランのメンバーEntityセキュリティには必要な情報が含まれている必要がありますので、UserDetailsを継承し、関連フィールドを超えてください.
JPAを使用してRepositoryを作成します.
MemberRepository
@Repository
public interface MemberRepository extends JpaRepository<Member, String> {
}
JPA Repositoryを継承してRepositoryを作成します.次に、MemberServiceとMemberServiceImplを作成します.
MemberService
public interface MemberService extends UserDetailsService {
}
UserDetailsServiceを継承しましょう.MemberServiceImpl
@Service
public class MemberServiceImpl implements MemberService {
@Autowired
private MemberRepository memberRepository;
@Autowired
private PasswordEncoder passwordEncoder;
private final AccountStatusUserDetailsChecker detailsChecker = new AccountStatusUserDetailsChecker();
@PostConstruct
public void init() {
memberRepository.save(Member.builder()
.userId("test")
.userPwd(passwordEncoder.encode("test"))
.userNm("테스트")
.gender("M")
.height(180)
.weight(80)
.privateYn("Y")
.regdate(Instant.now())
.roles(Collections.singletonList("ROLE_USER"))
.build()
);
}
@Override
public UserDetails loadUserByUsername(String userId) {
Member member = memberRepository.findById(userId).orElseThrow(() -> new UsernameNotFoundException("user is not exists"));
detailsChecker.check(member);
return member;
}
}
@PostConstructでテストユーザーを設定します.PasswordEncoderを使用するので、パスワードはenocde形式で挿入されます.
UserDetailsのloadUserByUserNameメソッドを上書きします.
認証プロバイダを追加して、後続のログイン情報を検証します.
OAuth2Provider
@Slf4j
@Component
public class OAuthProvider implements AuthenticationProvider {
@Autowired
private PasswordEncoder passwordEncoder;
@Autowired
private MemberRepository memberRepository;
@Override
public Authentication authenticate(Authentication authentication) {
String name = authentication.getName();
String password = authentication.getCredentials().toString();
Member member = memberRepository.findById(name)
.orElseThrow(() -> new UsernameNotFoundException("user is not exists"));
if(!passwordEncoder.matches(password, member.getPassword()))
throw new BadCredentialsException("password is not valid");
return new UsernamePasswordAuthenticationToken(name, password, member.getAuthorities());
}
@Override
public boolean supports(Class<?> authentication) {
return authentication.equals(
UsernamePasswordAuthenticationToken.class
);
}
}
では、Providerを使用するためにSecurityを変更します.SecurityConfig
@EnableWebSecurity
@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
private OAuthProvider oAuthProvider;
// @Override
// protected void configure(AuthenticationManagerBuilder auth) throws Exception {
// auth.inMemoryAuthentication()
// .withUser("user")
// .password("{bcrypt}$2a$10$Dp7dXcuT5cGW9clQRfJKIe22EVV7rNCjntXWBE6f0e8nPuu6GlRq6")
// .roles("USER");
// }
@Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable()
.headers().frameOptions().disable()
.and()
.authorizeRequests()
.antMatchers(
"/oauth/**",
"/oauth2/callback",
"/h2/**"
).permitAll()
.and()
.formLogin().and()
.authenticationProvider(oAuthProvider)
.httpBasic();
}
}
authenticationProvider(oAuthProvider)
この部分はProviderを使用している部分ですすべての設定が完了し、先ほど作成したユーザー情報でトークンを受信します.
http://localhost:1995/oauth/authorize?client_id=foo&redirect_uri=http://localhost:1995/oauth2/callback&response_type=code&scope=read
接続後に作成したユーザー情報を使用してログインすると、トークンが発行されていれば成功します.
Reference
この問題について(Spring Boot Outh 2認証サーバアプリケーション-5), 我々は、より多くの情報をここで見つけました https://velog.io/@papakang22/Spring-Boot-OAuth2-인증서버-적용기-5テキストは自由に共有またはコピーできます。ただし、このドキュメントのURLは参考URLとして残しておいてください。
Collection and Share based on the CC Protocol