Spring Boot Security OAuth2 自定义异常消息
Posted
技术标签:
【中文标题】Spring Boot Security OAuth2 自定义异常消息【英文标题】:Spring Boot Security OAuth2 custom exception message 【发布时间】:2020-05-26 04:00:08 【问题描述】:我的 Spring Boot RESTfull 项目中有些特殊情况,而不是身份验证异常错误消息的标准定制。我需要不同的消息,具体取决于用户名或密码是否错误,或者用户名不存在,或者用户是否在数据库中被停用。目前我只能收到消息"Bad credentials"
,我还没有找到任何解决方案如何根据某些用户属性或特殊情况自定义消息。
我目前有这样的自定义身份验证提供程序:
@Component
public class CustomAuthenticationProvider implements AuthenticationProvider
@Autowired
private CustomUserDetailsService userDetailsService;
@Autowired
PasswordEncoder passwordEncoder;
@Override
public Authentication authenticate(Authentication authentication)
throws org.springframework.security.core.AuthenticationException
String name = authentication.getName();
String password = authentication.getCredentials().toString();
UserDetails userDetails = userDetailsService.loadUserByUsername(name);
if(passwordEncoder.matches(password, userDetails.getPassword()))
return new UsernamePasswordAuthenticationToken(userDetails.getUsername(), userDetails.getPassword(),
userDetails.getAuthorities());
return null;
@Override
public boolean supports(Class<?> authentication)
return authentication.equals(UsernamePasswordAuthenticationToken.class);
我有这样的自定义用户详细信息服务:
@Service
public class CustomUserDetailsService implements org.springframework.security.core.userdetails.UserDetailsService
@Autowired
UserService userService; //my custom user service
@Override
public UserDetails loadUserByUsername(String username)
try
User user = userService.getUserByUsername(username);
if(user == null)
throw new UsernameNotFoundException("Username doesn't exist");
else if(user.isDeactivated())
throw new UsernameNotFoundException("User deactivated");
List<Authority> listOfAuthorities = userService.getAllAuthoritiesFromUser(user.getUserId());
List<GrantedAuthority> grantedAuthorities = new ArrayList<>();
for(Authority authority : listOfAuthorities)
grantedAuthorities.add(new SimpleGrantedAuthority(authority.getName()));
org.springframework.security.core.userdetails.User userNew =
new org.springframework.security.core.userdetails.User(user.getUsername(), user.getPassword(), grantedAuthorities);
return userNew;
catch(Exception ex)
throw new UsernameNotFoundException("Username or password not correct");
我在哪里可以处理来自throw new UsernameNotFoundException
的消息并将其返回为"error_description"
?
编辑
这也是我的SecurityConfig
和ResourceServerConfig
:
@Configuration
@EnableWebSecurity
@Order(Ordered.LOWEST_PRECEDENCE)
public class SecurityConfig extends WebSecurityConfigurerAdapter
@Autowired
CustomUserDetailsService userDetailsService;
@Autowired
private CustomAuthenticationProvider authProvider;
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception
auth.authenticationProvider(authProvider)
.userDetailsService(userDetailsService)
.passwordEncoder(passwordEncoder());
@Override
protected void configure(HttpSecurity http) throws Exception
http.csrf().disable();
http.addFilterBefore(new AuthenticationTokenFilter(authenticationManager()), BasicAuthenticationFilter.class);
// must be overriden and exposed as @Bean, otherwise boot's AuthenticationManagerConfiguration will take precedence
@Bean @Override
public AuthenticationManager authenticationManagerBean() throws Exception
return super.authenticationManagerBean();
@Bean
public PasswordEncoder passwordEncoder()
return new BCryptPasswordEncoder();
@Configuration
@EnableResourceServer
public class ResourceServerConfig extends ResourceServerConfigurerAdapter
@Autowired
private AuthExceptionEntryPoint myEntryPoint;
@Override
public void configure(HttpSecurity http) throws Exception
http.anonymous().and().authorizeRequests().antMatchers("/**")
.authenticated()
.and()
.exceptionHandling().authenticationEntryPoint(myEntryPoint).accessDeniedHandler(new OAuth2AccessDeniedHandler());
【问题讨论】:
***.com/a/19788700/6252399 -> 这看起来像是您正在寻找的解决方案 我添加了自定义入口点,但没有为/auth/token
端点调用它,该端点是用于身份验证的 oauth2 端点。
你解决了吗?
@aswzen 不是。我不得不进行额外的 API 调用来检查详细信息。
【参考方案1】:
Spring Security 上的这条通用消息是有目的的,它是为了混淆登录失败的实际原因。
一旦您根据需要提供特定消息,例如Username doesn't exist
、User deactivated
、Password incorrect
等等,你开始为恶意用户提供太多信息了。
更新
如果你仍然想这样做,你可以实现你自己的AuthenticationFailureHandler
,这样的东西应该可以工作:
public class DefaultAuthenticationFailureHandler extends SimpleUrlAuthenticationFailureHandler
@Override
public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response,
AuthenticationException exception) throws IOException, ServletException
super.onAuthenticationFailure(request, response, exception);
if (exception.getClass().isAssignableFrom(UsernameNotFoundException.class))
response.sendRedirect("User not found")
else if (exception.getClass().isAssignableFrom(LockedException.class))
response.sendRedirect("User Locked")
【讨论】:
感谢您的回答。我理解为什么默认情况下没有给出实际原因,但我有客户的具体要求。当需要更具体的消息时,是否有针对特定情况的解决方法? 再次感谢。由于我的项目是 RESTful Web 服务,我注意到添加自定义故障句柄的正确位置在哪里。我用ResourceServerConfig
和SecurityConfig
的代码更新了我的问题。以上是关于Spring Boot Security OAuth2 自定义异常消息的主要内容,如果未能解决你的问题,请参考以下文章
Understand Spring Security Architecture and implement Spring Boot Security