gpt4 book ai didi

java - 如何处理 UsernameNotFoundException spring security

转载 作者:行者123 更新时间:2023-12-02 09:11:03 26 4
gpt4 key购买 nike

如何处理UsernameNotFoundException

在 Spring Security 中,当找不到用户名时,UserDetailsS​​ervice 实现会抛出 UsernameNotFoundException。例如这样:

   @Override
@Transactional
public UserDetails loadUserByUsername(java.lang.String username) throws UsernameNotFoundException {
logger.info("Load user by username: {}", username);
User user = userRepository.findUserByUsername(username).orElseThrow(
() -> new UsernameNotFoundException("User Not Found with -> username or email: " + username));

return UserPrinciple.build(user);
}

我想构建一个自定义的“用户未找到 REST 响应”。我应该如何捕获/处理这个异常?我在 WebSecurityConfigurerAdapter 实现处理程序中实现了一个处理程序方法:

  private static void handleException(HttpServletRequest req, HttpServletResponse rsp, AuthenticationException e)
throws IOException {
PrintWriter writer = rsp.getWriter();
writer.println(new ObjectMapper().writeValueAsString(new AuthResponse("", null, null, null, null,
"Authentication failed.", false)));
rsp.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
}

但是这个方法应该等待 AuthenticationException 异常,并且在运行时异常的类型是 java.lang.NullPointerException 所以我无法进行强制转换或检索初始的UsernameNotFoundException

如有任何建议,我们将不胜感激。很多很多的问候:)。

最佳答案

安全层位于 Controller 和 @ControllerAdvice 中的任何内容之前。因此@ControllerAdviceUsernameNotFoundException 起不再是一个选项它是 AuthenticationException 的子类在身份验证期间抛出,使您的异常处理程序位于 @ControllerAdvice无法到达。

您只能使用 @ControllerAdviceResponseEntityExceptionHandler如果你扔UsernameNotFoundException Controller 内部或从 Controller 引用的任何其他 bean。

这是我的建议 - 您实现 AuthenticationFailureHandler并将其与 AuthenticationFilter 一起使用您用于安全配置的。Spring Boot Security 附带了大约 4 个用于安全相关问题的处理程序接口(interface)

  1. AccessDeniedHandler - 这可以处理用户没有所需角色等问题。
  2. AuthenticationEntryPoint - 这可以处理诸如用户尝试在没有适当身份验证元素的情况下访问资源等问题。

  3. AuthenticationFailureHandler - 这可以处理诸如找不到用户时(即 UsernameNotFoundException )或身份验证提供程序内部引发的其他异常等问题。事实上,这处理了 AccessDeniedException 未处理的其他身份验证异常。和AuthenticationEntryPoint .

  4. AuthenticationSuccessHandler - 这有助于在用户成功通过身份验证后执行重定向等操作。

请参阅以下示例片段,了解所有 4 个接口(interface)的实现。请根据您的喜好定制这些。

  1. AccessDeniedHandler实现
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.security.web.access.AccessDeniedHandler;
import org.springframework.stereotype.Component;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.OutputStream;

@Component
public class RestAccessDeniedHandler implements AccessDeniedHandler {

@Override
public void handle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, AccessDeniedException e) throws IOException, ServletException {

Map<String,Object> response = new HashMap<>();
response.put("status","34");
response.put("message","unauthorized api access");

//httpServletResponse.setStatus(HttpServletResponse.SC_FORBIDDEN);
httpServletResponse.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
OutputStream out = httpServletResponse.getOutputStream();
ObjectMapper mapper = new ObjectMapper();
mapper.writerWithDefaultPrettyPrinter().writeValue(out,response);
//mapper.writeValue(out, response);

out.flush();
}
}
  • AuthenticationEntryPoint实现
  • import com.fasterxml.jackson.databind.ObjectMapper;
    import org.springframework.http.HttpStatus;
    import org.springframework.security.core.AuthenticationException;
    import org.springframework.security.web.AuthenticationEntryPoint;
    import org.springframework.stereotype.Component;

    import javax.servlet.ServletException;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    import java.io.IOException;
    import java.io.OutputStream;

    @Component
    public class RestAuthenticationEntryPoint implements AuthenticationEntryPoint {

    @Override
    public void commence(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, AuthenticationException e) throws IOException, ServletException {

    Map<String,Object> response = new HashMap<>();
    response.put("status","34");
    response.put("message","unauthorized access");
    httpServletResponse.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
    OutputStream out = httpServletResponse.getOutputStream();
    ObjectMapper mapper = new ObjectMapper();
    mapper.writerWithDefaultPrettyPrinter().writeValue(out, response);
    out.flush();
    }
    }
  • AuthenticationFailureHandler实现
  • package com.ibiller.webservices.security;

    import com.fasterxml.jackson.databind.ObjectMapper;
    import org.springframework.http.HttpStatus;
    import org.springframework.security.core.AuthenticationException;
    import org.springframework.security.web.authentication.AuthenticationFailureHandler;
    import org.springframework.stereotype.Component;

    import javax.servlet.ServletException;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    import java.io.IOException;
    import java.io.OutputStream;


    @Component
    public class RestAuthenticationFailureHandler implements AuthenticationFailureHandler
    {
    @Override
    public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse httpServletResponse,
    AuthenticationException ex) throws IOException, ServletException
    {

    Map<String,Object> response = new HashMap<>();
    response.put("status","34");
    response.put("message","unauthorized access");

    httpServletResponse.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
    OutputStream out = httpServletResponse.getOutputStream();
    ObjectMapper mapper = new ObjectMapper();
    mapper.writerWithDefaultPrettyPrinter().writeValue(out, response);
    out.flush();
    }
    }
  • AuthenticationSuccessHandler实现
  • import org.springframework.security.core.Authentication;
    import org.springframework.security.web.authentication.AuthenticationSuccessHandler;
    import org.springframework.stereotype.Component;

    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    import java.io.IOException;

    @Component
    public class RestSuccessHandler implements AuthenticationSuccessHandler {

    public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException {
    Set<String> roles =
    AuthorityUtils.authorityListToSet(authentication.getAuthorities());
    if (roles.contains("ROLE_ADMIN")) {
    //do something
    }

    }
    }

    这是扩展 WebSecurityConfigurerAdapter 的安全配置将一切连接在一起。

    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.http.HttpStatus;
    import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
    import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
    import org.springframework.security.config.annotation.web.builders.HttpSecurity;
    import org.springframework.security.config.annotation.web.builders.WebSecurity;
    import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
    import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
    import org.springframework.security.config.http.SessionCreationPolicy;
    import org.springframework.security.web.AuthenticationEntryPoint;
    import org.springframework.security.web.authentication.AnonymousAuthenticationFilter;
    import org.springframework.security.web.authentication.HttpStatusEntryPoint;
    import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
    import org.springframework.security.web.util.matcher.OrRequestMatcher;
    import org.springframework.security.web.util.matcher.RequestMatcher;

    @Configuration
    @EnableWebSecurity
    @EnableGlobalMethodSecurity(
    prePostEnabled = true,
    securedEnabled = true,
    jsr250Enabled = true)
    public class SecurityConfiguration extends WebSecurityConfigurerAdapter {


    private static final RequestMatcher PROTECTED_URLS = new OrRequestMatcher(
    new AntPathRequestMatcher("/v1/**"),new AntPathRequestMatcher("/admin/**")
    );

    AuthenticationProvider provider;

    public SecurityConfiguration(final AuthenticationProvider authenticationProvider) {
    super();
    this.provider=authenticationProvider;
    }

    @Override
    protected void configure(final AuthenticationManagerBuilder auth) {
    auth.authenticationProvider(provider);
    }


    @Override
    public void configure(final WebSecurity webSecurity) {
    webSecurity.ignoring().antMatchers("/info/**");//url that will be ignored
    }

    @Override
    public void configure(HttpSecurity http) throws Exception {
    http.sessionManagement()
    .sessionCreationPolicy(SessionCreationPolicy.STATELESS)
    .and()
    .exceptionHandling()
    .accessDeniedHandler(accessDeniedHandler())
    .authenticationEntryPoint(authenticationEntryPoint())
    .and()
    .authenticationProvider(provider)
    .addFilterBefore(authenticationFilter(), AnonymousAuthenticationFilter.class)
    .authorizeRequests()
    .antMatchers("/v1/**").hasRole("API")
    .antMatchers("/admin/**").hasAnyRole("SUPER_ADMIN","ADMIN")
    .and()
    .csrf().disable()
    .formLogin().disable()
    .httpBasic().disable()
    .logout().disable();
    }

    @Bean
    AuthenticationFilter authenticationFilter() throws Exception {
    final AuthenticationFilter filter = new AuthenticationFilter(PROTECTED_URLS);
    filter.setAuthenticationManager(authenticationManager());
    filter.setAuthenticationSuccessHandler(successHandler());
    filter.setAuthenticationFailureHandler(authenticationFailureHandler());
    return filter;
    }

    @Bean
    RestAccessDeniedHandler accessDeniedHandler() {
    return new RestAccessDeniedHandler();
    }

    @Bean
    RestAuthenticationEntryPoint authenticationEntryPoint() {
    return new RestAuthenticationEntryPoint();
    }

    @Bean
    RestAuthenticationFailureHandler authenticationFailureHandler(){
    return new RestAuthenticationFailureHandler();
    }

    @Bean
    RestSuccessHandler successHandler(){
    return new RestSuccessHandler();
    }
    }

    关于java - 如何处理 UsernameNotFoundException spring security,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59417122/

    26 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com