如何处理UsernameNotFoundException
?
在Spring Security中,当未找到用户名时,UserDetailsService
实现将引发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
因此我无法强制转换或检索initial UsernameNotFoundException
。
任何意见,将不胜感激。许多问候:)。
安全层位于控制器和@ControllerAdvice
。因此@ControllerAdvice
不是一种选择,因为UsernameNotFoundException
这是AuthenticationException
在身份验证期间抛出的子类,从而使您的异常处理程序@ControllerAdvice
无法访问。
如果要扔进控制器或控制器引用的任何其他bean内@ControllerAdvice
,ResponseEntityExceptionHandler
则只能使用并且UsernameNotFoundException
。
这是我的建议-您AuthenticationFailureHandler
将其AuthenticationFilter
用于安全配置并与之配合使用。Spring Boot安全性附带约4个处理程序接口,用于处理与安全性相关的问题
AccessDeniedHandler
-处理诸如用户没有所需角色时的问题。AuthenticationEntryPoint
-处理诸如用户尝试在没有适当身份验证元素的情况下访问资源时的问题。
AuthenticationFailureHandler
-处理诸如找不到用户(即UsernameNotFoundException
)或身份验证提供程序内引发其他异常之类的问题。实际上,这可以处理AccessDeniedException
and 不能处理的其他身份验证异常AuthenticationEntryPoint
。
AuthenticationSuccessHandler
-这有助于在用户成功通过身份验证后执行重定向之类的工作。
有关所有4个接口的实现,请参见以下示例代码段。请根据自己的喜好自定义这些。
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();
}
}
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句