SpringBoot安全认证Security的实现方法

下面是Spring Boot安全认证Security的实现方法的完整攻略。

1. Spring Security简介

Spring Security是基于Spring框架的安全认证框架,在Spring Boot项目中可以很方便地实现用户身份认证和授权管理。

Spring Security提供了一个功能强大且灵活的框架,能够应对绝大多数的安全需求。它提供了许多可自定义的插件和配置选项,使得开发人员可以根据自身需求来定制安全策略。

2. 依赖管理

要使用Spring Security,需要在pom.xml文件中添加如下依赖:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-security</artifactId>
</dependency>

3. 配置Spring Security

3.1 配置用户信息

在Spring Security中,需要配置用户信息。可以在配置类中添加一个方法,返回一个UserDetails类型的对象。例如:

@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Bean
    public UserDetailsService userDetailsService() {
        String password = new BCryptPasswordEncoder().encode("123456");
        UserDetails user = User.withUsername("user")
                .password(password)
                .roles("USER")
                .build();
        return new InMemoryUserDetailsManager(user);
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests()
                .anyRequest().authenticated()
                .and()
                .formLogin().loginPage("/login").permitAll()
                .and()
                .logout().permitAll();
    }

}

上面的配置中,我们定义了一个用户,用户名为“user”,密码为“123456”,角色为“USER”。

3.2 配置安全策略

在SecurityConfig类中,我们需要重写WebSecurityConfigurerAdapter类中的configure(HttpSecurity http)方法,配置安全策略。

在这个方法中,我们可以设置哪些请求需要认证,哪些请求不需要认证,以及如何处理认证和授权过程。例如:

@Override
protected void configure(HttpSecurity http) throws Exception {
    http.authorizeRequests()
            .antMatchers("/css/**", "/index").permitAll() // 静态资源和首页不需要认证
            .antMatchers("/user/**").hasRole("USER") // user目录下的请求需要用户角色才能访问
            .and().formLogin().loginPage("/login").failureUrl("/login-error") // 自定义登录界面和失败页
            .and().exceptionHandling().accessDeniedPage("/401"); // 自定义权限不足页面
}

4. 示例

下面是两个简单的示例,演示如何使用Spring Security认证功能。

4.1 示例1:基本认证功能实现

首先,我们创建一个简单的Spring Boot项目,并添加如下依赖:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-security</artifactId>
</dependency>

然后,在配置类中添加如下配置:

@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Autowired
    private UserDetailsService userDetailsService;

    @Bean
    public PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(userDetailsService).passwordEncoder(passwordEncoder());
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests()
                .antMatchers("/css/**", "/index").permitAll()
                .antMatchers("/user/**").hasRole("USER")
                .and().formLogin().loginPage("/login").failureUrl("/login-error")
                .and().exceptionHandling().accessDeniedPage("/401");
    }
}

在我们的示例中,我们只为“user”这个用户配置了一个角色:USER。用户的密码经过了BCrypt加密,密码为“123456”。

创建一个UserController类:

@RestController
@RequestMapping("/user")
public class UserController {

    @GetMapping("/list")
    public String userList() {
        return "user list";
    }

    @GetMapping("/add")
    public String addUser() {
        return "add user";
    }
}

在UserController中,我们配置了两个请求:/user/list 和 /user/add。配置了“USER”角色的用户可以访问这两个请求,没有配置“USER”角色的用户则无法访问。

接下来我们需要创建一个登录页面和一个授权不足页面。

创建一个LoginController类:

@Controller
public class LoginController {

    @GetMapping("/login")
    public String login() {
        return "login";
    }

    @GetMapping("/login-error")
    public String loginError(Model model) {
        model.addAttribute("loginError", true);
        return "login";
    }
}

在这个类中,我们定义了两个请求:/login 和 /login-error。/login是我们的登录页面,/login-error是登录失败后的跳转页面。

在templates目录下创建login.html文件:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Login</title>
</head>
<body>
<div th:if="${loginError}">
    Invalid username or password!
</div>
<form th:action="@{/login}" method="post">
    <div>
        <label for="username">Username:</label>
        <input type="text" id="username" name="username"/>
    </div>
    <div>
        <label for="password">Password:</label>
        <input type="password" id="password" name="password"/>
    </div>
    <button type="submit">Sign in</button>
</form>
</body>
</html>

在public目录下创建401.html文件:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Access Denied</title>
</head>
<body>
<h1>Access Denied</h1>
<p>Sorry, you don't have permission to access this page.</p>
</body>
</html>

最后再创建一个启动类:

@SpringBootApplication
public class SecurityDemoApplication {
    public static void main(String[] args) {
        SpringApplication.run(SecurityDemoApplication.class, args);
    }
}

启动项目,访问http://localhost:8080/login,进入登录页面。输入用户名和密码(用户名为“user”,密码为“123456”),点击Sign in按钮,即可登录成功。

如果输入的用户名或密码错误,则会跳转到 /login-error 页面。如果有一个未授权的用户尝试访问/user/list或/user/add页面,就会被重定向到 /401 页面。

4.2 示例2:使用数据库存储用户信息

上面的示例中,我们通过在代码中硬编码的方式配置了用户名和密码。但在实际开发中,我们一般会将用户信息保存在数据库中。下面我们演示如何使用数据库存储用户信息。

首先,在pom.xml文件中添加如下依赖:

<dependency>
    <groupId>org.springframework.security</groupId>
    <artifactId>spring-security-data</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.security</groupId>
    <artifactId>spring-security-config</artifactId>
</dependency>

然后在数据库中创建两张表,users和authorities。其中users表用于保存用户信息,authorities表用于保存用户的权限信息。

create table users (
  username varchar(50) not null primary key,
  password varchar(100) not null,
  enabled boolean not null
);

create table authorities (
  username varchar(50) not null,
  authority varchar(50) not null,
  constraint fk_authorities_users foreign key (username) references users (username)
);

接下来,我们需要在SecurityConfig类中配置用户认证信息的来源,即UserDetailsService。UserDetailsService是一个接口,是用来获取用户详细信息的。我们可以使用Spring Security提供的JdbcUserDetailsManager来访问数据库中的用户信息。

@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Autowired
    private DataSource dataSource;

    @Bean
    public PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.jdbcAuthentication().dataSource(dataSource)
                .usersByUsernameQuery("select username,password,enabled from users where username = ?")
                .authoritiesByUsernameQuery("select username,authority from authorities where username = ?")
                .passwordEncoder(passwordEncoder());
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests()
                .antMatchers("/css/**", "/index").permitAll()
                .antMatchers("/user/**").hasRole("USER")
                .and().formLogin().loginPage("/login").failureUrl("/login-error")
                .and().exceptionHandling().accessDeniedPage("/401");
    }
}

这里我们配置了一个JdbcUserDetailsService,从users表和authorities表中获取用户的信息和角色信息。

最后,我们需要创建一个用于初始化用户信息的数据脚本。

执行以下SQL脚本,可以向users表和authorities表中插入初始数据:

insert into users (username, password, enabled) values ('admin', '$2a$10$5dAfNL4fb8TEqvg2Z9yYn.OrtlQfugCZaUEjoX9bnutgQqjRlWkM2', true);
insert into authorities (username, authority) values ('admin', 'ROLE_ADMIN');

在UserController类中添加一个/admin接口:

@RestController
@RequestMapping("/user")
public class UserController {

    @GetMapping("/list")
    public String userList() {
        return "user list";
    }

    @GetMapping("/add")
    public String addUser() {
        return "add user";
    }

    @GetMapping("/admin")
    @PreAuthorize("hasRole('ADMIN')")
    public String admin() {
        return "admin page";
    }
}

在配置类SecurityConfig中添加一个君子,向/ADMIN路径授权:

@Override
protected void configure(HttpSecurity http) throws Exception {
    http.authorizeRequests()
            .antMatchers("/css/**", "/index").permitAll()
            .antMatchers("/user/**").hasRole("USER")
            .antMatchers("/admin/**").hasRole("ADMIN")
            .and().formLogin().loginPage("/login").failureUrl("/login-error")
            .and().exceptionHandling().accessDeniedPage("/401");
}

完成之后,启动Spring Boot应用,访问http://localhost:8080/login,输入用户名和密码(用户名为“admin”,密码为“123456”),点击登陆按钮。输入正确的用户名和密码后,成功进入应用。在地址栏输入http://localhost:8080/user/add,可以看到访问成功。但是当访问http://localhost:8080/user/admin路劲时,将会被重定向到401页面,表示您没有admin角色,没有访问的权限。

以上就是SpringBoot安全认证Security的实现方法的攻略,希望能对你有所帮助。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:SpringBoot安全认证Security的实现方法 - Python技术站

(0)
上一篇 2023年5月20日
下一篇 2023年5月20日

相关文章

  • 如何使用Java编译期注解?

    下面是关于“如何使用Java编译期注解”的完整使用攻略。 什么是编译期注解? 编译期注解是在Java编译期间处理的一种注解,它可以被编译器直接解释和处理。编译器可以识别和处理这些注解,并在编译期执行相应的操作。相比于运行时注解,编译期注解更加高效、可靠和安全。 如何使用Java编译期注解? 使用Java编译期注解需要按照以下步骤进行: 1. 定义注解类 首先…

    Java 2023年5月11日
    00
  • 详解Java使用JMH进行基准性能测试

    详解Java使用JMH进行基准性能测试 性能测试对于Java应用程序的开发和优化是至关重要的。在Java中,可以使用JMH框架进行严密的基准测试,以确保在实际生产环境中获得最高的性能和最小的延迟。 介绍JMH框架 JMH是一个专业级的基准测试框架,它可以提供准确的基准测试结果。它提供了多种的方式来测试不同的Java代码片段,包括方法调用、对象实例化、算法等。…

    Java 2023年5月26日
    00
  • 这么优雅的Java ORM没见过吧!

    首先,我们需要了解Java ORM的概念。ORM(Object Relational Mapping)是指对象关系映射,是一种将面向对象的程序与关系型数据库之间进行数据转换的技术。Java中有很多ORM框架,如Hibernate、MyBatis、JPA等,它们可以帮助开发者更加方便、高效地访问数据库。 接下来,我们来了解一款优雅的Java ORM框架——Jo…

    Java 2023年5月20日
    00
  • java开发之spring webflow实现上传单个文件及多个文件功能实例

    Java开发之Spring Webflow实现上传单个文件及多个文件功能实例 介绍 Spring Webflow是Spring框架的扩展模块,可以帮助我们实现基于流程的Web应用程序。在Web应用程序中,文件上传功能是常见需求之一,本文将介绍如何使用Spring Webflow实现上传单个文件及多个文件功能。 上传单个文件 1. Maven依赖 在pom.x…

    Java 2023年5月20日
    00
  • Sprint Boot @JsonInclude使用方法详解

    @JsonInclude是Spring Boot中的一个注解,用于指定在序列化Java对象为JSON字符串时,哪些字段需要包含在内。在本文中,我们将详细介绍@JsonInclude注解的作用和使用方法,并提供两个示例。 @JsonInclude注解的作用 @JsonInclude注解用于指定在序列化Java对象为JSON字符串时,哪些字段需要包含在内。当使用…

    Java 2023年5月5日
    00
  • JVM的垃圾回收算法一起来看看

    JVM的垃圾回收算法 在Java编程中,内存管理是一个非常重要的问题。Java虚拟机(JVM)的垃圾回收算法可以用来管理和清理不再使用的内存空间。本文将带你了解JVM的垃圾回收算法并提供一些示例。 垃圾回收算法 标记-清除(Mark and Sweep) 这是最早的垃圾回收算法之一,也是最容易实现的算法之一。该算法包括两个步骤:标记和清除。 标记阶段扫描堆中…

    Java 2023年5月19日
    00
  • Java自学书籍Top 10

    下面我详细介绍一下“Java自学书籍Top 10”的攻略: 一、为什么要学Java? 在介绍Java自学书籍的攻略之前,我们先来了解一下为什么要学Java。Java是目前使用比较广泛的编程语言之一,它具有以下特点: Java是一种跨平台的语言,可以在不同操作系统上运行。 Java具有比较好的可读性和易于维护性。 Java拥有庞大的用户群体和丰富的开源库,方便…

    Java 2023年5月23日
    00
  • 在Java中轻松使用工厂设计模式介绍

    在Java中轻松使用工厂设计模式介绍 概述 工厂设计模式(Factory design pattern)是一种常用的设计模式,它将对象的创建过程抽象出来,使得代码的可维护、可扩展性提高,并且能够让我们避免使用new关键字直接创建对象。Java中有两种主要的工厂设计模式:工厂方法模式(Factory Method Pattern)和抽象工厂模式(Abstrac…

    Java 2023年5月26日
    00
合作推广
合作推广
分享本页
返回顶部