[Spring Boot] Spring-Security 로그인

이맑음·2021년 10월 6일
0

Spring Boot

목록 보기
13/21
post-thumbnail

fastcampus 웹 개발 마스터 초격차 패키지를 수강하며 정리한 내용들입니다.

로그인

  • 스프링 프레임워크에서 로그인이란 authenticated = true인 Authentication 객체를 SecurityContext에 가지고 있는 상태이다. 이때 객체가 AnonymousAuthenticationToken가 아니어야 한다.
  • Authentication = 통행증
  • Authentication이 가지고 있는 정보
    1. Set authorities : 인증된 권한 정보
    2. principal : 인증 대상에 관한 정보. 주로 UserDetails 객체
    3. credentials : 인증 확인을 위한 정보. 주로 비밀번호이지만, 인증 후에는 보안을 위해 삭제
    4. details : 그 밖에 필요한 정보. IP, 세션정보, 기타 인증요청에서 사용했던 정보들.
    5. boolean authenticated : 인증이 되었는지를 체크

폼 로그인

DefaultLoginPageGeneratingFilter

  • GET /login을 처리한다.
  • 별도의 로그인 페이지를 설정하지 않으면 제공되는 필터이다.
  • 기본 로그인 폼을 제공한다.

UsernamePasswordAuthenticationFilter

  • POST /login을 처리한다.
  • form 인증을 처리해주는 필터로 스프링 시큐리티에서 가장 일반적으로 사용한다.

예제

  • config/SecurityConfig
@EnableWebSecurity(debug = true)
@EnableGlobalMethodSecurity(prePostEnabled = true) 
// 사용시 컨트롤러에 작성한 롤 대로 실행(유저 로그인->관리자 페이지 볼 수 없음)
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    private final CustomAuthDetails customAuthDetails;

    public SecurityConfig(CustomAuthDetails customAuthDetails) {
        this.customAuthDetails = customAuthDetails;
    }

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception { 계정 생성 하는 부분 }

    @Bean
    RoleHierarchy roleHierarchy(){
        RoleHierarchyImpl roleHierarchy = new RoleHierarchyImpl();
        roleHierarchy.setHierarchy("ROLE_ADMIN > ROLE_USER");
        return roleHierarchy;
    }
  // admin 계정으로 로그인 시, user 계정이 가지고 있는 권한들을 모두 사용할 수 있다.

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
                .authorizeRequests(request->{
                    request
                            .antMatchers("/").permitAll()
                            // 홈페이지에 대해 모든 접속 허용
                            .anyRequest().authenticated()
                           // 홈페이지를 제외한 페이지에 인증 검사 수행
                            ;
                })
                .formLogin(
                        login->login.loginPage("/login")
  // login()에 접속할 페이지를 따로 지정해주지 않으면 default 로그인 페이지를 보여준다.
                                .permitAll()
  // 위에서 모든 페이지에 대한 인증 검사를 요구했기에 permitAll을 사용하지 않으면 무한루프에 빠질 수 있다.
                                .defaultSuccessUrl("/", false)
  // defaultSuccessUrl을 true해주면 유저 페이지에서 로그인을 성공하여도 메인 페이지로 리턴시켜준다.
                                .failureUrl("/login-error").authenticationDetailsSource(customAuthDetails)
                )
                .logout(logout-> logout.logoutSuccessUrl("/"))
  // 로그아웃 성공시 루트(홈페이지)로 이동
                .exceptionHandling(exception->exception.accessDeniedPage("/access-denied"))
  // user1으로 로그인시 관리자 페이지에 접속하면 보여줄 페이지를 지정
                ;
    }

    @Override
    public void configure(WebSecurity web) throws Exception {
        // 위에서 루트 페이지를 제외한 페이지에 인증을 요구하도록 했기에 css에 대해서 ignore 시켜준다.
        web.ignoring()
                .requestMatchers(
                        PathRequest.toStaticResources().atCommonLocations()
                )
                ;
    }
}
  

예제2 - Authentication의 details custom하기

  • controller/HomeController에 /auth 페이지 추가
    @ResponseBody //결과를 json으로 보기 위해 사용
    @GetMapping("/auth")
    public Authentication auth(){
        return SecurityContextHolder.getContext().getAuthentication();
    }
  • config/RequestInfo
@Data
@AllArgsConstructor
@NoArgsConstructor
@Builder
public class RequestInfo {

    private String remoteIp;
    private String sessionId;
    private LocalDateTime loginTime;
}
  • config/CustomAuthDetails
@Component
public class CustomAuthDetails implements AuthenticationDetailsSource<HttpServletRequest, RequestInfo> {

    @Override
    public RequestInfo buildDetails(HttpServletRequest request) {
        return RequestInfo.builder()
                .remoteIp(request.getRemoteAddr())
                .sessionId(request.getSession().getId())
                .loginTime(LocalDateTime.now())
                .build();
    }
}
  • admin 계정으로 로그인 후 /auth 페이지로 이동하면 아래와 같이 custom한 details를 볼 수 있다.
  {
  "authorities": [
    {
      "authority": "ROLE_ADMIN"
    }
  ],
  "details": {
    "remoteIp": "0:0:0:0:0:0:0:1",
    "sessionId": "~~~",
    "loginTime": "2021-10-06T11:21:28.373"
  },
  "authenticated": true,
  "principal": {
    "password": null,
    "username": "admin",
    "authorities": [
      {
        "authority": "ROLE_ADMIN"
      }
    ],
    "accountNonExpired": true,
    "accountNonLocked": true,
    "credentialsNonExpired": true,
    "enabled": true
  },
  "credentials": null,
  "name": "admin"
}

0개의 댓글