SpringSecurity 自定义表单登录的实现

下面是SpringSecurity自定义表单登录的实现攻略:

1. 确定用户信息来源

在进行 SpringSecurity 表单登录认证之前,我们需要确定用户信息的来源。通常,我们可以从数据库、LDAP、Active Directory 或者使用第三方的 SAML/OAuth2 身份验证服务中获取用户信息,这里我们以数据库中获取用户信息为例。

2. 用户认证流程

SpringSecurity 表单登录认证的流程如下:

  1. 用户访问需要进行认证的资源,如 /login 页面。
  2. 进入登录页面后,用户输入用户名和密码,提交表单。
  3. SpringSecurity 接收请求,对用户名和密码进行认证。
  4. 如果用户名和密码正确,SpringSecurity 为用户生成一个令牌,并把令牌返回给客户端。
  5. 后续的每个请求都会携带该令牌信息,SpringSecurity 通过此令牌对请求进行权限校验。

3. 实现步骤

下面是自定义表单登录的实现步骤:

3.1 导入所需依赖

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

3.2 实现 UserDetailsSerrvice 接口

@Service
public class CustomUserDetailsService implements UserDetailsService {

  @Autowired
  private UserRepository userRepository;

  @Override
  public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
    User user = userRepository.findByUsername(username);
    if(user == null) {
      throw new UsernameNotFoundException("用户名不存在!");
    }

    return new org.springframework.security.core.userdetails.User(
            user.getUsername(),
            user.getPassword(),
            user.getAuthorities());
  }
}

UserDetailsService 接口用于从数据库中获取用户信息。

3.3 实现 AuthenticationProvider 接口

@Component
public class CustomAuthenticationProvider implements AuthenticationProvider {

  @Autowired
  private CustomUserDetailsService userDetailsService;

  @Override
  public Authentication authenticate(Authentication authentication) throws AuthenticationException {
    String username = authentication.getName();
    String password = (String) authentication.getCredentials();

    UserDetails userDetails = userDetailsService.loadUserByUsername(username);
    if(!password.equals(userDetails.getPassword())) {
      throw new BadCredentialsException("密码不正确!");
    }

    return new UsernamePasswordAuthenticationToken(username, password, userDetails.getAuthorities());
  }

  @Override
  public boolean supports(Class<?> authentication) {
    return authentication.equals(UsernamePasswordAuthenticationToken.class);
  }
}

AuthenticationProvider 接口用于对用户的登陆信息进行认证。

3.4 配置 Security

@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {

  @Autowired
  private CustomAuthenticationProvider customAuthenticationProvider;

  @Override
  protected void configure(AuthenticationManagerBuilder auth) throws Exception {
    auth.authenticationProvider(customAuthenticationProvider);
  }

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

在 SecurityConfig 中,我们指定了 CustomAuthenticationProvider 来进行认证,还配置了登录页面的路径、认证成功后跳转的页面路径。

3.5 创建登录页面

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>登录</title>
</head>
<body>
  <form action="/login" method="post">
    <label for="username">用户名:</label>
    <input type="text" id="username" name="username"><br>

    <label for="password">密码:</label>
    <input type="password" id="password" name="password"><br>

    <input type="submit" value="登录">
  </form>
</body>
</html>

4. 示例

下面提供两个示例:

4.1 基于 JPA 的用户认证

@Service
public class CustomUserDetailsService implements UserDetailsService {

  @Autowired
  private UserRepository userRepository;

  @Override
  public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
    User user = userRepository.findByUsername(username);
    if(user == null) {
      throw new UsernameNotFoundException("用户名不存在!");
    }

    return new org.springframework.security.core.userdetails.User(
            user.getUsername(),
            user.getPassword(),
            user.getAuthorities());
  }
}

@Component
public class CustomAuthenticationProvider implements AuthenticationProvider {

  @Autowired
  private CustomUserDetailsService userDetailsService;

  @Override
  public Authentication authenticate(Authentication authentication) throws AuthenticationException {
    String username = authentication.getName();
    String password = (String) authentication.getCredentials();

    UserDetails userDetails = userDetailsService.loadUserByUsername(username);
    if(!password.equals(userDetails.getPassword())) {
      throw new BadCredentialsException("密码不正确!");
    }

    return new UsernamePasswordAuthenticationToken(username, password, userDetails.getAuthorities());
  }

  @Override
  public boolean supports(Class<?> authentication) {
    return authentication.equals(UsernamePasswordAuthenticationToken.class);
  }
}

@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {

  @Autowired
  private CustomAuthenticationProvider customAuthenticationProvider;

  @Override
  protected void configure(AuthenticationManagerBuilder auth) throws Exception {
    auth.authenticationProvider(customAuthenticationProvider);
  }

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

4.2 基于 MyBatis 的用户认证

@Repository
public interface UserMapper {

  @Select("select * from user where username = #{username}")
  User findByUsername(String username);
}

@Service
public class CustomUserDetailsService implements UserDetailsService {

  @Autowired
  private UserMapper userMapper;

  @Override
  public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
    User user = userMapper.findByUsername(username);
    if(user == null) {
      throw new UsernameNotFoundException("用户名不存在!");
    }

    return new org.springframework.security.core.userdetails.User(
            user.getUsername(),
            user.getPassword(),
            user.getAuthorities());
  }
}

@Component
public class CustomAuthenticationProvider implements AuthenticationProvider {

  @Autowired
  private CustomUserDetailsService userDetailsService;

  @Override
  public Authentication authenticate(Authentication authentication) throws AuthenticationException {
    String username = authentication.getName();
    String password = (String) authentication.getCredentials();

    UserDetails userDetails = userDetailsService.loadUserByUsername(username);
    if(!password.equals(userDetails.getPassword())) {
      throw new BadCredentialsException("密码不正确!");
    }

    return new UsernamePasswordAuthenticationToken(username, password, userDetails.getAuthorities());
  }

  @Override
  public boolean supports(Class<?> authentication) {
    return authentication.equals(UsernamePasswordAuthenticationToken.class);
  }
}

@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {

  @Autowired
  private CustomAuthenticationProvider customAuthenticationProvider;

  @Override
  protected void configure(AuthenticationManagerBuilder auth) throws Exception {
    auth.authenticationProvider(customAuthenticationProvider);
  }

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

以上就是 SpringSecurity 自定义表单登录的实现攻略及两个示例。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:SpringSecurity 自定义表单登录的实现 - Python技术站

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

相关文章

  • JSP页面文件中base标记用法实例分析

    当我们在开发JSP(Java Server Pages)页面时,经常会遇到需要使用外部资源的情况,例如引入外部css文件、js文件等。在这种情况下,我们需要设置一个统一的URI,让所有的资源都基于这个URI来获取,这时我们可以使用<base>标记。 <base>标记是HTML语言中的元素,用于指定URL基础适配器(base URI a…

    Java 2023年6月15日
    00
  • jsp实现仿QQ空间新建多个相册名称并向相册中添加照片功能

    实现仿QQ空间新建多个相册名称并向相册中添加照片功能需要进行以下步骤: 准备工作 确定基础环境:使用JSP,需要安装Java和Tomcat等环境。 安装数据库:本文以MySQL为例进行讲解,需要安装MySQL数据库,并创建相应的数据库和表格。 创建数据库和表格 在MySQL中创建相应的数据库,例如“photo_album”。 在该数据库下创建两个表格:一个用…

    Java 2023年6月15日
    00
  • 完整详解Java开发学习路线指南

    完整详解Java开发学习路线指南 Java是一门非常流行的编程语言,在软件开发领域具有广泛的应用。如果想要成为一名Java开发人员,需要掌握一系列的知识和技能。下面是一个Java开发学习路线的完整攻略,希望可以帮助大家快速入门Java开发。 学习基础知识 Java开发的第一步是掌握基础知识。以下是Java开发初学者需要掌握的几个基本概念: 数据类型 Java…

    Java 2023年5月20日
    00
  • SpringBoot入门教程详解

    Spring Boot是一个非常流行的Java Web框架,它可以帮助开发者快速地构建Web应用程序。在本攻略中,我们将详细介绍如何使用Spring Boot,并提供两个示例来说明其用法。 以下是两个示例,介绍如何使用Spring Boot: 示例一:使用Spring Boot构建一个简单的Web应用程序 首先,我们需要在pom.xml文件中添加以下依赖: …

    Java 2023年5月15日
    00
  • 在springboot中添加mvc功能的正确姿势讲解

    下面是关于“在springboot中添加mvc功能的正确姿势讲解”的完整攻略,包含两个示例说明。 在Spring Boot中添加MVC功能的正确姿势讲解 在Spring Boot中添加MVC功能非常简单,只需要添加相应的依赖和配置即可。下面是一个简单的步骤: 步骤1:添加依赖 首先,我们需要在pom.xml中添加Spring Boot Web依赖。以下是一个…

    Java 2023年5月17日
    00
  • 详解Java如何利用位操作符创建位掩码

    让我来给你详细讲解Java如何利用位操作符创建位掩码的完整攻略。 什么是位掩码? 位掩码是一个二进制数字,在这个数字中的每一位都表示一个不同的布尔值,通常被用于标识一组开关或选项。 如何利用位操作符创建位掩码? Java中,有三种可用的位操作符,分别是“按位与&”、“按位或|”和“按位异或^”操作符。其中,“按位与&”操作符用于对比两个二进制…

    Java 2023年5月20日
    00
  • Java实现简单酒店管理系统

    Java实现简单酒店管理系统 概述 在本教程中,我们将使用Java语言实现一个简单的酒店管理系统,包括以下功能: 添加/查询客房信息 预订客房 退房 我们将使用OOP开发方法,并实现以下几个类: Room:客房类,包括房间号、是否入住、房间类型等属性 Hotel:酒店类,包括所有客房列表等属性和行为 Receptionist:前台类,负责处理客户请求 细节 …

    Java 2023年5月18日
    00
  • Java语言的缺点是什么?

    Java作为一种非常流行的编程语言,它具有很多优点,但也有一些缺点。本文将详细讲解Java语言的缺点。 内存消耗较高 Java语言的内存消耗较高,这是由于Java程序在运行时需要将代码转换为字节码,然后再由JVM解释执行。这种过程需要占用大量的内存资源。另外,Java中的垃圾回收机制也会占用大量的内存。这些都会导致Java程序的内存占用较高,特别是在处理大量…

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