如何使用默认类从 JSON 登录尝试中读取用户凭据?
Posted
技术标签:
【中文标题】如何使用默认类从 JSON 登录尝试中读取用户凭据?【英文标题】:How can I read the user credentials from a JSON login attempt using default classes? 【发布时间】:2020-03-18 18:02:09 【问题描述】:我正在关注Implementing JWT Authentication on Spring Boot APIs 上的教程,在作者的 JWTAuthenticationFilter 类的关键部分(听起来就是这样),他从 POST 请求的 JSON 正文中检索用户名和密码到登录端点.
因此,使用 curl
或 Postman 或其他东西,您可以使用包含 "username":"joe", "password":"pass"
之类的请求正文 POST 到 /login。
作者的身份验证过滤器使用此方法将此 JSON 映射到 ApplicationUser 实例:
@Override
public Authentication attemptAuthentication(HttpServletRequest req,
HttpServletResponse res) throws AuthenticationException
try
ApplicationUser creds = new ObjectMapper()
.readValue(req.getInputStream(), ApplicationUser.class);
return authenticationManager.authenticate(
new UsernamePasswordAuthenticationToken(
creds.getUsername(),
creds.getPassword(),
new ArrayList<>())
);
catch (IOException e)
throw new RuntimeException(e);
足够好,但要做到这一点,他创建了一个自定义类 ApplicationUser 以及一个客户 UserDetailsService、一个 UserController 和一个 ApplicationUserRepository,所有这些都与他自己的特殊内存数据库后端一起工作。在我真正的 Spring Boot 应用程序中,我使用默认数据库模式并让 Spring Boot 通过 JDBC 对用户进行身份验证。它适用于表单身份验证。这是我的 WebSecurityConfigurerAdapter 中的一点:
@Autowired
private DataSource dataSource;
@Override
public void configure(AuthenticationManagerBuilder builder) throws Exception
builder .jdbcAuthentication()
.dataSource(dataSource);
所以我的问题是,attemptAuthentication
方法需要如何从教程的代码中更改?我猜测默认实现可能是User.class
,并尝试将其插入导入“creds
”的表达式中,如下所示:
User creds = new ObjectMapper().readValue(request.getInputStream(), User.class);
那没用。我得到了这个例外:
webapp_1 | 2019-11-22 15:54:43.234 WARN 1 --- [nio-8080-exec-2] n.j.w.g.config.JWTAuthenticationFilter : inputstream: org.apache.catalina.connector.CoyoteInputStream@1477c9d5
webapp_1 | 2019-11-22 15:54:43.298 ERROR 1 --- [nio-8080-exec-2] o.a.c.c.C.[.[.[/].[dispatcherServlet] : Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception
webapp_1 |
webapp_1 | java.lang.RuntimeException: com.fasterxml.jackson.databind.exc.InvalidDefinitionException: Cannot construct instance of `org.springframework.security.core.userdetails.User` (no Creators, like default construct, exist): cannot deserialize from Object value (no delegate- or property-based Creator)
我不想只是深入研究User
的子类,因为我实际上什至不知道它是否是正确的类,或者我什至在这里是否需要它。我可以以其他方式从我的 JSON POST 中提取username
和password
,也许绕过ObjectMapper()
的使用?或者我应该在这里创建一个私有内部类?总而言之,问题是:在 Spring Boot 中使用默认的基于 JDBC 的用户实现时,如何才能最好地适应这种“attemptAuthentication
”方法?
【问题讨论】:
【参考方案1】:我找到了一个可行的解决方案,尽管我仍然认为必须有一种更优雅的方式来做到这一点。我所做的是定义一个静态内部类LoginAttempt
并使用ObjectMapper
来读取JSON 作为它的一个实例。
我发现如果没有 static
修饰符,Jackson 无法反序列化内部类(请参阅 this question),但使用“static
”它可以工作。
来自JWTAuthenticationFilter
的相关代码为:
static class LoginAttempt
private String username;
private String password;
public LoginAttempt()
public String getUsername() return username;
public String getPassword() return password;
public void setUsername(String username) this.username = username;
public void setPassword(String password) this.password = password;
@Override
public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException
try
LoginAttempt creds = new ObjectMapper().readValue(request.getInputStream(), LoginAttempt.class);
return authenticationManager.authenticate(
new UsernamePasswordAuthenticationToken(
creds.getUsername(),
creds.getPassword(),
new ArrayList<>()
)
);
catch( IOException e )
throw new RuntimeException(e);
【讨论】:
以上是关于如何使用默认类从 JSON 登录尝试中读取用户凭据?的主要内容,如果未能解决你的问题,请参考以下文章
如何在 json 的帮助下使用 PHP、MySql 在 android 中验证用户登录凭据
如何使用下面的类从web服务中动态读取下面给出的JSON数据,并为收到的数据创建水平列表视图。
如果 maxSessionsPreventsLogin 设置为 true 并且某些使用我的登录凭据的用户尝试登录,如何在我的 thymelaf 登录页面中显示错误?