当我们创建用于提供服务或Web应用程序的API时,为项目提供身份验证和授权至关重要。在这篇文章中,我将讲述如何使用弹簧安全模块制作必要的安全配置。
开始,我将创建一个带有两个端点“/”/“,”/“欢迎”的RestController,并尝试运行该应用程序并查看发生的情况。
@RestController
public class HomeController {
@GetMapping("/")
public String sayHello() {
return "Welcome to Spring Security!";
}
@GetMapping("/welcome")
public String sayHello() {
return "Welcome to Spring Security(Protected)!";
}
}
这是结果!
让我们看看如果我们将Spring Security添加到项目依赖性
中会发生什么
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
现在,如果我们运行应用程序并尝试击中和端点,您将被重定向到下面的登录页面。
好吧,我不记得添加/login
端点或配置任何用户。但是如何渲染登录页面,为什么?
仅通过将依赖项添加到ClassPath来启用弹簧安全。默认情况下,所有路由/端点都需要身份验证才能访问。但是,哪些证书用于登录?我不记得配置任何凭据!这是因为如果我们不配置它,弹簧将在运行时间提供默认的随机凭据
安全配置
Spring MVC在通过一组过滤器后,将所有传入的HTTP请求发送到名为DispatcherServlet
的单个Servlet。调度员负责将HTTP请求发送到相应的控制器。
当我们将Spring Security添加到类Path时,将一组安全过滤器添加到过滤器链中。这些过滤器拦截了每个HTTP请求,然后才能进入控制器。这是Spring Security验证HTTP请求并决定转发或拒绝请求的地方。
默认情况下,每个HTTP请求都是认证的。但是,我们可以通过制作自己的安全配置来覆盖这种行为
为了做到这一点,我们需要提供我们的自定义SecurityFilterChain
bean
默认行为是由于bean
@Bean
@Order(SecurityProperties.BASIC_AUTH_ORDER)
SecurityFilterChain defaultSecurityFilterChain(HttpSecurity http) throws Exception {
http.authorizeHttpRequests().anyRequests().authenticated();
http.formLogin();
http.httpBasic();
return http.build();
}
现在,我们可以在这样的全新配置类中拥有自己的豆子。
@Configuration
class ApiSecurityConfiguration {
@Bean
SecurityFilterChain customSecurityFilterChain(HttpSecurity http) throws Exception {
http.authorizeHttpRequests((requests)-> requests
.requestMatchers("/welcome").authenticated()
.anyRequests().authenticated());
.formLogin();
.httpBasic(Customizer.withDefaults());
return http.build();
}
}
上面的配置使/welcome
端点是身份验证的,并且除了公开访问的任何端点
,但我们仍然没有设置自己的用户集。
在使用用户设置前进之前,我们需要了解如何处理请求。
UserDetailsService
(接口)-> loadUserByUserName(String username)
这是加载用户特定数据的核心接口
UserDetailsManager
(接口扩展了UserDetailsservice)允许创建,更新,删除UserDetails(请参阅下面的方法签名)的USERDETAILSERVICE的扩展
createUser(UserDetails user)
updateUser(UserDetails user)
deleteUser(String username user)
changePassword(String oldPwd, String newPwd)
userExists(String username)
Spring Security提供的示例实现类(用于UserDetailsManager
接口)为InMemoryUserDetailsManager
,JdbcUserDetailsManager
,LdapUserDetailsManager
上述所有接口和类都使用界面
UserDetails
,它提供核心用户信息
为了证明用户详细信息的身份,我们需要实现UserDetailsService
接口并将其作为弹簧bean提供。我们可以使用Spring提供的默认实现,或者我们可以拥有自己的自定义实现。
如果我们要构建企业应用程序,建议您拥有自己的自定义实施。但是为简单起见,我们将使用提供的默认实现
在这篇文章中,我们将看到如何配置InMemoryUserDetailsManager
@Bean
UserDetailsService userDetailsService() {
UserDetails admin = User.withDefaultPasswordEncoder()
.username("admin")
.password("12345")
.authorities("admin")
.build();
UserDetails user = User.withDefaultPasswordEncoder()
.username("user")
.password("54321")
.authorities("read")
.build();
return new InMemoryUserDetailsManager(user, admin);
}
在这里,我们正在使用DefaultPasswordEncoder()
。但是,总的来说,我们需要提供一个PasswordEncoder
豆。春季为我们提供了许多密码编码器
例如,
@Bean
PasswordEncoder passwordEncoder() {
return new BCryptyPasswordEncoder()
}
现在,使用这些配置,我们可以使用Inmemory中提供的用户访问受保护的路线。
我们还可以使用Spring Security提供的默认JdbcUserDetailsManager
Bean从数据库中获取用户
为了使用它,我们需要有一个数据源
我们将使用MySQL进行此应用程序。 DataSource配置是在applications.properties
文件中完成的,或者我们有application.yml
spring:
datasource:
platform: mysql
url: jdbc:mysql://localhost:5432/mydb
username: foo
password: bar
jpa:
show-sql: true
properties:
hibernate:
format_sql: true
默认情况下,JdbcUserDetailsManager
默认实现,假设我们遵循具有users(id, username, password, enabled)
和authorities(id, username, authority)
表的数据库架构
因此,如果我们使用的是JdbcUserDetailsManager
实现,我们需要遵循相同的DDL模式
用JdbcUserDetailsManager
bean替换InMemoryUserDetailsManager
bean(确保通过datasoucrce对象)
@Bean
UserDetailsService userDetailsService(DataSource dataSource) {
return new JdbcUserDetailsManager(dataSource)
}
好吧,我们已经配置了我们的应用程序以使用inmemory userDetails,并配置为使用默认实现从数据库中获取用户详细信息。
,但这对于企业应用程序还不够,因为我们可能会根据客户建议在数据库中遵循同一命名约定。在这种情况下,我们不能使用JdbcUserDetailsManager
。
但这是另一天的话题。
我将在下一篇文章中写更多有关它的信息。