我正在使用Angular 7和Spring Boot实现一个登录页面,我正在处理一个失败的登录。基本上,我想在X登录尝试失败后锁定登录特定时间。
HttpSecurity配置
@Override
protected void configure(HttpSecurity http) throws Exception {
logger.info("#### Configuring Security ###");
JWTAuthenticationFilter jwtAuthenticationFilter = new JWTAuthenticationFilter(authenticationManager());
jwtAuthenticationFilter.setFilterProcessesUrl("/rest/users/authenticate");//this override the default relative url for login: /login
http
.httpBasic().disable()
.csrf().disable()
.authorizeRequests()
.antMatchers("/rest/", "/rest/helloworld/**").permitAll()
.anyRequest().authenticated()
.and().exceptionHandling().authenticationEntryPoint(new JwtAuthenticationEntryPoint()).and()
.addFilter(jwtAuthenticationFilter);
为了处理登录,我创建了一个过滤器
public class JWTAuthenticationFilter extends UsernamePasswordAuthenticationFilter {
private static Logger logger = Logger.getLogger(JWTAuthenticationFilter.class);
private AuthenticationManager authenticationManager;
public JWTAuthenticationFilter(AuthenticationManager authenticationManager) {
this.authenticationManager = authenticationManager;
}
@Override
public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException {
try {
UserDto credentials = new ObjectMapper().readValue((request.getInputStream()), UserDto.class);
return authenticationManager.authenticate(
new UsernamePasswordAuthenticationToken(
credentials.getUserName(),
credentials.getPassword(),
new ArrayList<>())
);
} catch (IOException e) {
throw new RuntimeException(e);
}
}
@Override
protected void successfulAuthentication(HttpServletRequest request, HttpServletResponse response, FilterChain chain, Authentication authResult) throws IOException, ServletException {
//sucessfull authentication stuff
}
@Override
protected void unsuccessfulAuthentication(HttpServletRequest request, HttpServletResponse response, AuthenticationException failed) throws IOException, ServletException {
logger.info("Authentication failed");
ErrorMessage errorMessage = new ErrorMessage("access_denied", "Wrong email or password.");
String jsonObject = JSONUtil.toJson(errorMessage);
//processing authentication failed attempt
UserDto credentials = new ObjectMapper().readValue((request.getInputStream()), UserDto.class);
AuthenticationService authenticationService = Application.getApplicationContext().getBean(AuthenticationService.class);
int numFailedAttemptLogin = authenticationService.authenticationFailedAttempt(credentials.getUserName());
response.setStatus(403);
PrintWriter out = response.getWriter();
out.print(jsonObject);
out.flush();
out.close();
//super.unsuccessfulAuthentication(request, response, failed);
}
}
登录工作正常,没有问题。我的问题是不成功的身份验证方法。当用户输入错误的凭据时,会引发Bad凭据异常,并调用不成功的身份验证方法。在这里,我需要再次访问请求表单以提取用户名并处理身份验证失败的尝试,我得到了以下异常
java.io.IOException: Stream closed
这是因为在attemptAuthentication方法中,请求inputstream是读取的,并且显然是关闭的。
如何在未成功的身份验证中访问请求正文信息?
我试过SecurityContextHolder。getContext()。getAuthentication(),但由于身份验证失败,它为空。
有人知道吗?
最好的问候
在遵循M.Deinum的建议后,我能够创建一个监听特定异常的组件:
@Component
public class AuthenticationEventListener implements ApplicationListener<ApplicationEvent> {
private static Logger logger = Logger.getLogger(AuthenticationEventListener.class);
@Override
public void onApplicationEvent(ApplicationEvent applicationEvent) {
logger.info(String.format("Event types: %s", applicationEvent.getClass()));
if (applicationEvent instanceof AbstractAuthenticationFailureEvent) {
String username = ((AbstractAuthenticationFailureEvent) applicationEvent).getAuthentication().getName();
if (applicationEvent instanceof AuthenticationFailureBadCredentialsEvent) {
logger.info(String.format("User %s failed to login", username));
//this.handleFailureEvent(username, event.getTimestamp());
}
}
}
}
这种方法是使用异常来驱动在特定场景中要做的事情。我能够实现类似的事情,继续使用我的JWTAuthentiationFilter,就像这样
@Override
public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException {
try {
UserDto credentials = new ObjectMapper().readValue((request.getInputStream()), UserDto.class);
try {
return authenticationManager.authenticate(
new UsernamePasswordAuthenticationToken(
credentials.getUserName(),
credentials.getPassword(),
new ArrayList<>())
);
} catch (BadCredentialsException bce) {
try {
handleBadCredentials(credentials, response);
throw bce;
} catch (LockedException le) {
handleUserLocked(credentials, response);
throw le;
}
}
} catch (IOException e) {
throw new RuntimeException(e);
}
}
@Override
protected void unsuccessfulAuthentication(HttpServletRequest request, HttpServletResponse response, AuthenticationException authException) throws IOException, ServletException {
logger.info("Authentication failed");
response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
response.setContentType(MediaType.TEXT_PLAIN_VALUE);
response.getWriter().print(authException.getLocalizedMessage());
response.getWriter().flush();
}
感谢你们的时间和帮助,非常感谢。
我在Azure App服务上有一个Spring web应用程序,它使用Microsoft JDBC驱动程序连接到Azure SQL DB,并使用访问令牌进行身份验证。它最初可以工作,但过了一段时间后,我开始得到SQLServerException:登录失败,用户'NT Authority\Anonymous Logon' 我正在遵循MS文档中概述的步骤。 com.microsoft.sqlserv
问题内容: 我无法摆脱这个错误。我已经通过SSMS添加了“ NT AUTHORITY \ NETWORK”用户以及使用此线程作为参考的相关角色:用户“ NT AUTHORITY \ NETWORKSERVICE”的登录失败 我试图通过Windows服务建立数据库连接。在调试模式下,数据库连接可以正常工作。当我实际尝试运行已安装的服务时,便会出现此错误。 这是我来自app.config的连接字符串:
所以阅读Sybase的实用手册,我发现我可以设置我的 localhost服务器使用dsedit.exe.。 然后我尝试在Aqua Data Studio中注册我的localhost服务器,方法如下: 但是我得到了以下错误: 管理员用户名是什么 我在哪里/如何设置它?? 根据文档,它说默认的系统管理员ID是“sa”,没有密码。。 (http://infocenter.sybase.com/archi
所以我被这个令人沮丧的问题困住了。我对Firebase上的Google身份验证还很陌生,但我已经做了Firebase文档中关于如何集成Google登录身份验证的所有说明,然而我仍然在控制台中收到这个奇怪的错误,包括两个部分: 而且还 在有人试图指出以前就堆栈溢出提出的类似问题之前,以下是我在看到所有可用的解决方案之后所做的,但non已经解决了该错误 我有我的项目的SHA1指纹 我有我的OAUTH2
问题内容: 我试图测试与本地sql DB的连接。我有这个代码: 我尝试了很多用户。我的Windows用户是SOSCOMP,没有密码。我也知道SQL 2008将用户创建为“ sys”“ dbo”,我也尝试过这些。我总是得到: 有任何想法吗? 谢谢 问题答案: 如果尝试连接使用Windows身份验证的数据库,则可以在连接字符串中使用“ integratedSecurity”选项。