24 Şubat 2019 Pazar

SpringSecurity ExceptionHandlingConfigurer Sınıfı - HttpSecurity İle Kullanılır Login Başarısız İse Çağrılır

accessDeniedHandler metodu
Hatalı kullanıcı adı, şifresi gönderilmişse çağrılır.

Örnek
Elimizde şöyle bir kod olsun.
@Component
public class CustomAuthenticationFailureHandler implements AuthenticationFailureHandler {
  @Override
  public void onAuthenticationFailure(HttpServletRequest request,
                                      HttpServletResponse response,
      AuthenticationException ex) throws IOException, ServletException {
    response.setStatus(HttpStatus.UNAUTHORIZED.value());
    ...
  }
}
Şöyle yaparız.
@Configuration
@EnableWebSecurity
@ComponentScan("your.base.package")
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
 @Override
  protected void configure(final HttpSecurity http) throws Exception {
    http.exceptionHandling().accessDeniedHandler(accessDeniedHandler());
}

  @Bean
  public AccessDeniedHandler accessDeniedHandler() {
    return new CustomAuthenticationFailureHandler();
  }
}
accessDeniedPage metodu
Örnek
Şöyle yaparız.
httpSecurity.exceptionHandling().accessDeniedPage("/login?accessDenied");  
Örnek
Şöyle yaparız.
HttpSecurity http = ...;

http
  ...
  .and()
  .exceptionHandling().accessDeniedPage("/errors/error403")
  .and()
  ...
authenticationEntryPoint metodu
Doğrulanmamış kullanıcıyı ana sayfaya yönlendirir.

REST için kullanıyorsak başka sayfaya yönlendirmeye gerek yok, sadece HTTP 401 Unauthorized gönderilir.

Örnek
Şöyle yaparızAuthenticationEntryPoint nesnesi geçilir.
http.exceptionHandling().authenticationEntryPoint(new CustomEntryPoint());
Örnek
Şöyle yaparızz
.exceptionHandling()
  .accessDeniedHandler((request, response, accessDeniedException) -> {
    response.setContentType(MediaType.APPLICATION_JSON_VALUE);
    response.setStatus(HttpServletResponse.SC_FORBIDDEN);
      objectMapper.writeValue(
        response.getWriter(),
        ErrorResponseBody
          .builder()
          .code(ErrorType.ACCESS_DENIED)
          .status(HttpServletResponse.SC_FORBIDDEN)
          .message("Access denied")
          .build()
      );
    })
    .authenticationEntryPoint((request, response, authException) -> {
      response.setContentType(MediaType.APPLICATION_JSON_VALUE);
      response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
        objectMapper.writeValue(
          response.getWriter(),
            ErrorResponseBody
              .builder()
              .code(ErrorType.LOGIN_REQUIRED)
              .status(HttpServletResponse.SC_UNAUTHORIZED)
              .message("You are not authorized to access this resource")
              .build()
            );
    })

SpringSecurity AuthenticationFailureHandler Arayüzü

Örnek
Şöyle yaparız.
@Component
public class CustomAuthenticationFailureHandler implements AuthenticationFailureHandler
{
  @Override
  public void onAuthenticationFailure(HttpServletRequest request,
                                      HttpServletResponse response,
      AuthenticationException ex) throws IOException, ServletException
  {
    response.setStatus(HttpStatus.UNAUTHORIZED.value());
    ...
  }
}

SpringMVC @ResponseStatus Anotasyonu

Metod İle Kullanım
Açıklaması şöyle.
@ResponseStatus isn't very flexible. It marks the entire method so you have to be sure that your handler method will always behave the same way. And you still can't set the headers. You'd need the HttpServletResponse or a HttpHeaders parameter.
Örnek - OK
Şöyle yaparız.
@RequestMapping(value = "/patchdetails", method = RequestMethod.GET)
@ResponseStatus(value = HttpStatus.OK)
public String patchDetail() {
  return "patchDetails";
}
Örnek - Created
Şöyle yaparız.
@RequestMapping(method = RequestMethod.POST)
@ResponseStatus(value = HttpStatus.CREATED)
public void registerUser(RequestParam(required = true)) {...}
Exception Sınıfı İle Kullanım
Bu anotasyon daha çok exception'lar ile kullanmak için uygun.
reason Alanı
Şöyle yaparız.
@ResponseStatus(value = HttpStatus.UNAUTHORIZED, reason = "Invalid authorization")
public class AuthorizationException extends RuntimeException {}
value Alanı
Örnek
Elimizde şöyle bir kod olsun.
@ResponseStatus(HttpStatus.NOT_FOUND)
public class UserNotFoundException extends RuntimeException {
  public UserNotFoundException(String message) {
    super(message);
  }
}
Şöyle yaparız.
@Service
public class UserServiceImpl implements UserService {

  @Autowired
  private UserDAO userDAO;

  @Override
  public User getById(Long id) {
    return userDAO.findById(id)
      .orElseThrow(() -> new UserNotFoundException("No user with id = " + id));
  }
}
Örnek
Şöyle yaparız.
@ResponseStatus(HttpStatus.NOT_FOUND)
public class NotFoundException extends RuntimeException {

  private final int errorId;

  public NotFoundException(String errorMsg) {
    super("-1," + errorMsg);
    this.errorId = -1;
  }

  public NotFoundException(int errorId, String errorMsg) {
    super(errorId + "," + errorMsg);
    this.errorId = errorId;
  }

  public int getErrorId() {
    return errorId;
  }
}