포토그램 인증 구현하기
로그인구현
회원전보 수정 구현
PrincipalDetailsService.java에 loadUserByUsername함수를 꾸며줘야하는데
password는 필요없어도 되는게 시큐리티가 알아서 비교해주기 때문에 username 만 있어도 충분하다.
username가 있는지 없는지 확인할라면 UserRepository가 필요하다.
@RequiredArgsConstructor
@Service
public class PrincipalDetailsService implements UserDetailsService{
private final UserRepository userRepository;
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
return null;
}
}
Java
복사
UserRepository.java에서 JPA query method 를 사용할거다.
JpaRepository라는게 유저테이블에 있는 모든 데이터를 들고와라
등등 PagingAndSortingRepository를 또 타고 들어가면 save를 통해 insert 할 수 있고 삭제할 수 있다. 하지만 제한적이라는 것
그래서 밑에 사이트 접속해서 Query Creation 검색해서 찾아보면
를 보면서 사용하면
public interface UserRepository extends JpaRepository<User, Integer>{
//JPA query method
User findByUsername(String username);
}
Java
복사
username을 찾아서 user오브젝트로 리턴해준다
PrincipalDetailsService.java
// 1. 패스워드는 알아서 체킹하니까 신경쓸 필요가 없다.
// 2. 리턴이 잘되면 자동으로 세션을 만든다.
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
User userEntity = userRepository.findByUsername(username);
if(userEntity == null) {
return null;
}else {
return userEntity;
}
}
Java
복사
하지만 이렇게 진행하면 return 타입이랑 리턴해주는 타입이 안맞아서 오류난다.
userEntity를 UserDetails타입으로 바꿔줘야하는데 new를 진행해서 하면 더 복잡해지기 때문에 우선은 null로 바꿔주고 진행하고 auth 폴더안에 PrincipalDetails.java 생성
package com.cos.photogramstart.config.auth;
import java.util.Collection;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;
public class PrincipalDetails implements UserDetails{
private static final long serialVersionUID = 1L;
@Override
public Collection<? extends GrantedAuthority> getAuthorities() {
// TODO Auto-generated method stub
return null;
}
@Override
public String getPassword() {
// TODO Auto-generated method stub
return null;
}
@Override
public String getUsername() {
// TODO Auto-generated method stub
return null;
}
@Override
public boolean isAccountNonExpired() {
// TODO Auto-generated method stub
return false;
}
@Override
public boolean isAccountNonLocked() {
// TODO Auto-generated method stub
return false;
}
@Override
public boolean isCredentialsNonExpired() {
// TODO Auto-generated method stub
return false;
}
@Override
public boolean isEnabled() {
// TODO Auto-generated method stub
return false;
}
}
Java
복사
얘를 리턴시키도록 하자.
PrincipalDetailsService.java
package com.cos.photogramstart.config.auth;
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.cos.photogramstart.domain.user.User;
import com.cos.photogramstart.domain.user.UserRepository;
import lombok.RequiredArgsConstructor;
@RequiredArgsConstructor
@Service
public class PrincipalDetailsService implements UserDetailsService{
private final UserRepository userRepository;
// 1. 패스워드는 알아서 체킹하니까 신경쓸 필요가 없다.
// 2. 리턴이 잘되면 자동으로 UserDetails 타입을 세션으로 만든다.
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
User userEntity = userRepository.findByUsername(username);
if(userEntity == null) {
return null;
}else {
return new PrincipalDetails();
}
}
}
Java
복사
그리고 @Data도 추가.
private User user;
public PrincipalDetails(User user) {
this.user = user;
}
Java
복사
그러면 여기가 오류나니까
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
User userEntity = userRepository.findByUsername(username);
if(userEntity == null) {
return null;
}else {
return new PrincipalDetails(userEntity);
}
}
Java
복사
userEntity를 넣어주면 된다!!!
new PrincipalDetails(userEntity)가 세션이 저장될때 세션에 저장된 User 오브젝트를 나중에도 활용할 수 있다.
package com.cos.photogramstart.config.auth;
import java.util.Collection;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;
import com.cos.photogramstart.domain.user.User;
import lombok.Data;
@Data
public class PrincipalDetails implements UserDetails{
private static final long serialVersionUID = 1L;
private User user;
public PrincipalDetails(User user) {
this.user = user;
}
@Override
public Collection<? extends GrantedAuthority> getAuthorities() {
// TODO Auto-generated method stub
return null;
}
@Override
public String getPassword() {
return user.getPassword();
}
@Override
public String getUsername() {
return user.getUsername();
}
@Override
public boolean isAccountNonExpired() { //계정이 만료가 되었는
return true; //false가 맞는거다(로그인을 위해서 true로 변경)
}
@Override
public boolean isAccountNonLocked() {//계정이 잠겼는가
return true; //false가 맞는거다(로그인을 위해서 true로 변경)
}
@Override
public boolean isCredentialsNonExpired() { //비밀번호가 오랫동안 안바뀐거 아닌가
return true; //false가 맞는거다(로그인을 위해서 true로 변경)
}
@Override
public boolean isEnabled() { //계정이 활성화 되어있는가
return true; //false가 맞는거다(로그인을 위해서 true로 변경)
}
}
Java
복사
@Override
public Collection<? extends GrantedAuthority> getAuthorities() {
// TODO Auto-generated method stub
return null;
}
Java
복사
잘보면 요부분이 권한관련 부분인데
//권한: 한개가 아닐 수 있음. (3개 이상의 권한)
@Override
public Collection<? extends GrantedAuthority> getAuthorities() {
Collection<GrantedAuthority> collector = new ArrayList<>();
collector.add(new GrantedAuthority() {
@Override
public String getAuthority() {
return user.getRole();
}
});
return collector;
}
Java
복사
Collection 타입때문에 이렇게 지저분하게 변경됐다 이걸 람다식으로 깔끔하게 처리하면
//권한: 한개가 아닐 수 있음. (3개 이상의 권한)
@Override
public Collection<? extends GrantedAuthority> getAuthorities() {
Collection<GrantedAuthority> collector = new ArrayList<>();
collector.add(() -> {
return user.getRole();
});
return collector;
}
Java
복사
요렇게 심플하게 바꿀 수 있다.
add 안에 함수를 넣고 싶었던게 목적.
자바에서는 매개변수에 함수를 못넣는다. 자바는 함수가 일급객체가 아니기 때문에
여기에 인터페이스를 넣어줘야한다. 혹은 클래스 오브젝트를 넘긴다.
다시 로그인을 진행해보자.
로그인 성공! 404 코드가 떳다는건
/ 주소는 우리가 전에 403코드로 다른 주소로 이동하게 했었는데 403으로 안뜨고 404로 뜬건 로그인이 성공했다는 뜻이다.
/user 주소 쳐도 404코드가 나온다
확실하게 알고싶으면
다시 주소에 http://localhost:8080/logout 쳐서 로그아웃하고
주소에 http://localhost:8080/user 라 쳐도 메인로그인 화면으로 넘어온다
왜냐면 세션이 없어서 그렇다.