java - 尝试在 Spring Security 中使用 JDBC 身份验证时出错
问题描述
我正在尝试使用 Spring Security 的 JDBC 身份验证来对简单 Web 项目中的用户进行身份验证。在这个项目中,我将 Java 与 Spring boot 和 Spring Security、Thymeleaf 和 Bootstrap 一起使用。在这里,我有以下配置:
pom.xml:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.4.5</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.each.bd2</groupId>
<artifactId>PetDonation</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>PetDonation</name>
<description>Web application that help people to donate and/or adopt pets</description>
<properties>
<java.version>11</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
配置项目安全性的类:
package com.each.bd2.PetDonation.config;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import javax.sql.DataSource;
@Configuration
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
DataSource dataSource;
@Override
protected void configure(HttpSecurity httpSecurity) throws Exception{
httpSecurity
.authorizeRequests()
.antMatchers("/home/**", "/usuario/novo")
.permitAll()
.anyRequest()
.authenticated()
.and()
.formLogin(form -> form
.loginPage("/login").defaultSuccessUrl("/usuario/home", true)
.permitAll())
.csrf().disable();
}
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
BCryptPasswordEncoder encoder = new BCryptPasswordEncoder();
auth.jdbcAuthentication().dataSource(dataSource)
.passwordEncoder(encoder)
.usersByUsernameQuery("select username, password, enabled from users where username=?")
.authoritiesByUsernameQuery("select username, authority from authorities where username=?");
}
}
用户类(这里,我的用户名是电子邮件):
package com.each.bd2.PetDonation.config;
import com.each.bd2.PetDonation.entities.Usuario;
import com.fasterxml.jackson.annotation.JsonIgnore;
import javax.persistence.*;
import javax.validation.constraints.NotBlank;
import java.io.Serializable;
import java.util.*;
@Entity
@Table(name = "users")
public class Users implements Serializable {
private static final long serialVersionUID = 1L;
@Id
@NotBlank
private String username;
@NotBlank
private String password;
private boolean enabled;
@ElementCollection
@CollectionTable(name = "authorities", joinColumns = @JoinColumn(name = "username"))
//@OneToMany(mappedBy = "users")
private Set<Authorities> authorities = new HashSet<>();
@OneToOne(cascade = CascadeType.ALL, mappedBy = "user", fetch = FetchType.LAZY)
Usuario usuario;
public Users() {
}
public Users(String username, String password, boolean enabled) {
this.username = username;
this.password = password;
this.enabled = enabled;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public boolean isEnabled() {
return enabled;
}
public void setEnabled(boolean enabled) {
this.enabled = enabled;
}
public Set<Authorities> getAuthorities() {
return authorities;
}
public void addAuthority(String authority) {
this.authorities.add(new Authorities(authority));
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Users that = (Users) o;
return username.equals(that.username) && password.equals(that.password);
}
@Override
public int hashCode() {
return Objects.hash(username, password);
}
}
权威类:
package com.each.bd2.PetDonation.config;
import javax.persistence.*;
import java.io.Serializable;
import java.util.Objects;
@Embeddable
public class Authorities{
private String authority;
public Authorities() {}
public Authorities(String authority) {
this.authority = authority;
}
}
登录控制器:
package com.each.bd2.PetDonation.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
@Controller
public class LoginController {
@GetMapping
@RequestMapping("/login")
public String login(){
return "login";
}
}
登录 HTML:
<html lang="en" xmlns:th="http://www.w3.org/1999/xhtml">
<meta charset="UTF-8">
<head></head>
<body>
<div class="container">
<h1>Entrar</h1>
<div class="card row justify-content-center align-items-center mb-3 ml-4">
<form th:action="@{/login}" class="card-body" method="post">
<div class="form-group mb-3 col-5">
<label for="username">Email</label>
<input name="username" class="form-control" placeholder="email"/>
</div>
<div class="form-group mb-3 col-5">
<label for="password">Senha</label>
<input type="password" name="password" class="form-control" placeholder="senha"/>
</div>
<button class="btn btn-success justify-content-center" type="submit">Login</button>
</form>
</div>
</div>
</body>
</html>
我还有一个注册类,我确定它正在工作,因为在我的数据库中,我有以下插入用户的示例(我正在使用 BCryptPasswordEncoder 对我的密码进行编码): 这里
好吧,毕竟这一切。当我尝试对自己进行身份验证时,我收到以下信息: 登录页面
编辑1:
在这里您可以找到包含整个项目的存储库:https ://github.com/marco-fpereira/pet-donation/tree/master
这是尝试登录导致的spring security调试日志:(对不起,我不能直接在这里粘贴图像)
解决方案
推荐阅读
- javascript - Vuetify 工具提示在悬停时刷新/重新渲染
- css - CSS 模块不更改 DOM/标记类名 - 包裹捆绑器
- r - 通过评估反向引用替换 gsub 中的文本
- sql - 从开始日期和结束日期生成日期范围 SQL Azure
- php - 如何在数组中的所有其他元素之间添加一个元素
- python - Jupyter Notebook - 环境错误:
- javascript - JSON 的查询语言或如何在 Python 中使用 Javascript/Lua?
- javascript - Solidity:从我的智能合约中显示价值以做出反应的问题
- python - Windows 上的 Neovim 找不到 python 提供程序
- python - 有没有办法在 Python 中同时使用两个列表执行计算?