SpringSecurity 表单登录的实现

实现SpringSecurity表单登录需要以下步骤:

  1. 导入依赖

需要在项目中导入SpringSecurity相关的依赖包,例如:

<dependency>
   <groupId>org.springframework.security</groupId>
   <artifactId>spring-security-web</artifactId>
   <version>5.5.0</version>
</dependency>
<dependency>
   <groupId>org.springframework.security</groupId>
   <artifactId>spring-security-config</artifactId>
   <version>5.5.0</version>
</dependency>
  1. 配置SpringSecurity

在SpringBoot项目中,可以通过在配置类上加上@EnableWebSecurity注解,来启用SpringSecurity。接着在配置类中,可以定义拦截器规则、用户信息等相关配置,例如:

@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
    @Autowired
    private MyUserDetailsService myUserDetailsService;

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

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

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

上述配置中,我们配置了一个自定义的用户详情服务MyUserDetailsService,并且指定了密码加密的实现类BCryptPasswordEncoder。在configure(HttpSecurity http)方法中,我们设定了拦截器规则,对于URI为/login的请求,不需要进行身份验证,对于其他URI的请求,需要进行身份验证。

  1. 创建登录页面

接下来,创建一个登录页面,代码中含有一个POST请求方法,用于接收用户提交的登录表单。

<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8">
        <title>Login</title>
    </head>

    <body>
        <div>
            <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>
        </div>
    </body>    
<html>
  1. 实现自定义用户详情服务

在前面的配置中,我们指定了一个自定义的用户详情服务MyUserDetailsService,需要自己实现该服务来获取用户的详细信息,例如:

@Service
public class MyUserDetailsService 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(username + " not found");
        }

        Collection<SimpleGrantedAuthority> authorities = new ArrayList<>();
        for (Role role : user.getRoles()) {
            authorities.add(new SimpleGrantedAuthority(role.getName()));
        }

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

通过自定义用户详情服务,可以使用自己的业务逻辑从数据库或其他持久化层获取用户的信息。上述代码中,我们使用了一个自定义的实体类User来封装用户的信息,同时也使用了自定义的实体类Role来封装用户的角色信息。

  1. 定义自定义登录成功处理器

我们可以定义一个自定义的登录成功处理器来处理登录成功后的相关业务逻辑。例如:

@Component
public class CustomAuthenticationSuccessHandler extends SimpleUrlAuthenticationSuccessHandler {
    @Override
    public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response,
            Authentication authentication) throws ServletException, IOException {
        response.setStatus(HttpServletResponse.SC_OK);
    }
}

上述代码中,定义了一个CustomAuthenticationSuccessHandler类,继承了SimpleUrlAuthenticationSuccessHandler类,并重写了onAuthenticationSuccess方法。该方法会在用户登录成功后被调用,并可以在该方法中,处理登录成功后的业务逻辑。在该示例中,我们只是简单地设置了HTTP响应状态为200。

示例1:实现SpringSecurity表单登录的完整示例

下面是一个完整的SpringBoot项目中的完整示例:

@SpringBootApplication
public class SpringBootSecurityApplication {

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

    @Configuration
    @EnableWebSecurity
    public class SecurityConfig extends WebSecurityConfigurerAdapter {
        @Autowired
        private MyUserDetailsService myUserDetailsService;

        @Autowired
        private CustomAuthenticationSuccessHandler customAuthenticationSuccessHandler;

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

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

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

    @Service
    public class MyUserDetailsService 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(username + " not found");
            }

            Collection<SimpleGrantedAuthority> authorities = new ArrayList<>();
            for (Role role : user.getRoles()) {
                authorities.add(new SimpleGrantedAuthority(role.getName()));
            }

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

    @Component
    public class CustomAuthenticationSuccessHandler extends SimpleUrlAuthenticationSuccessHandler {
        @Override
        public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, 
                Authentication authentication) throws ServletException, IOException {
            response.setStatus(HttpServletResponse.SC_OK);
        }
    }

    @Entity
    public class User {
        @Id
        @GeneratedValue(strategy = GenerationType.IDENTITY)
        private Long id;
        private String username;
        private String password;

        @ManyToMany(fetch = FetchType.EAGER)
        private Set<Role> roles;

        // getter & setter
    }

    @Entity
    public class Role {
        @Id
        @GeneratedValue(strategy = GenerationType.IDENTITY)
        private Long id;
        private String name;

        // getter & setter
    }

    public interface UserRepository extends JpaRepository<User, Long> {
        User findByUsername(String username);
    }
}

示例2:使用 Thymeleaf 模板引擎实现 SpringSecurity 表单登录

下面是一个使用Thymeleaf模板引擎的SpringBoot项目中的完整示例:

@SpringBootApplication
public class SpringBootSecurityApplication {

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

    @Configuration
    @EnableWebSecurity
    public class SecurityConfig extends WebSecurityConfigurerAdapter {
        @Autowired
        private MyUserDetailsService myUserDetailsService;

        @Autowired
        private CustomAuthenticationSuccessHandler customAuthenticationSuccessHandler;

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

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

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

    @Service
    public class MyUserDetailsService 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(username + " not found");
            }

            Collection<SimpleGrantedAuthority> authorities = new ArrayList<>();
            for (Role role : user.getRoles()) {
                authorities.add(new SimpleGrantedAuthority(role.getName()));
            }

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

    @Component
    public class CustomAuthenticationSuccessHandler extends SimpleUrlAuthenticationSuccessHandler {
        @Override
        public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response,
                Authentication authentication) throws ServletException, IOException {
            response.setStatus(HttpServletResponse.SC_OK);
        }
    }

    @Entity
    public class User {
        @Id
        @GeneratedValue(strategy = GenerationType.IDENTITY)
        private Long id;
        private String username;
        private String password;

        @ManyToMany(fetch = FetchType.EAGER)
        private Set<Role> roles;

        // getter & setter
    }

    @Entity
    public class Role {
        @Id
        @GeneratedValue(strategy = GenerationType.IDENTITY)
        private Long id;
        private String name;

        // getter & setter
    }

    public interface UserRepository extends JpaRepository<User, Long> {
        User findByUsername(String username);
    }

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

    @Controller
    public class HomeController {
        @GetMapping("/home")
        public String home() {
            return "home";
        }
    }
}

上述代码中,我们使用了Thymeleaf来实现了一个自定义的登录页面,在该登录页面中,通过表单提交用户名和密码,并将数据提交到/loginURI。同时,也定义了一个自定义的控制器HomeController,在用户登录成功后,会跳转到该控制器中定义的/homeURI。

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

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

相关文章

  • Spring Boot如何集成模板引擎FreeMarker

    下面是 Spring Boot 集成 FreeMarker 模板引擎的完整攻略。 一、引入依赖 在 pom.xml 中添加 FreeMarker 和 Spring Boot 的依赖,如下所示: <dependency> <groupId>org.springframework.boot</groupId> <arti…

    Java 2023年5月31日
    00
  • Java实现中国象棋游戏

    Java实现中国象棋游戏攻略 1. 概述 本攻略主要介绍如何使用Java语言实现中国象棋游戏。将分为以下几个部分: 实现界面和交互 实现棋局数据和规则 实现人机交互功能 2. 实现界面和交互 实现游戏界面和交互模块可以使用Swing/AWT的图形界面库,实现如下功能: 显示当前棋局 实现棋子移动交互 实现游戏结束时弹出对话框 下面是一个简单的Swing界面实…

    Java 2023年5月19日
    00
  • Spring JPA学习之delete方法示例详解

    Spring JPA学习之delete方法示例详解 简介 Spring JPA框架提供了强大的CRUD功能,其中delete方法作为JPA中的删除操作,可以非常方便地删除数据库中的数据。本文将为大家详细讲解Spring JPA的delete方法,并提供两个示例。 方法介绍 删除操作在JPA中使用delete()方法,它有多种实现方式,分别为: 根据实体对象删…

    Java 2023年5月20日
    00
  • 带你深入理解MyBatis缓存机制

    当我们在使用 MyBatis 操作数据库时,缓存是一个非常重要的机制。它可以帮助我们优化性能并减轻数据库负载。MyBatis 缓存可以分为一级缓存和二级缓存。在本文中,我们将详细介绍这两种缓存机制以及其原理和使用。以下是本文将要涉及到的主要内容: 什么是 MyBatis 缓存机制 一级缓存实现原理及使用 一级缓存的局限性 二级缓存实现原理及使用 二级缓存的配…

    Java 2023年5月20日
    00
  • Java中的Object类用法总结

    Java中的Object类用法总结 在Java中,每个类都是Object类的子类,因此Object类提供了一些通用方法可以用于任何对象,本文将总结Object类的用法。 Object类中的常用方法 equals() equals()方法用于比较两个对象的值是否相等,但需要注意的是,==运算符比较的是两个对象的引用是否相等,而不是值。 示例: String s…

    Java 2023年5月26日
    00
  • JavaWeb Servlet实现文件上传与下载功能实例

    下面是 “JavaWeb Servlet实现文件上传与下载功能实例” 的完整攻略。 一、准备工作 在开始实现文件上传与下载功能之前,我们需要准备如下环境和工具: JDK:Java开发环境,最好使用JDK 1.8及以上版本; Eclipse:Java IDE,也可以使用其他Java IDE,比如IntelliJ IDEA等; Tomcat:JavaWeb服务器…

    Java 2023年5月19日
    00
  • JSP上传文件到指定位置实例代码

    下面我将详细讲解“JSP上传文件到指定位置实例代码”的完整攻略: 标题 JSP上传文件到指定位置实例代码 代码实现步骤 首先在 JSP 页面中使用 input 标签设置一个文件上传表单: <form action="upload.jsp" method="post" enctype="multipart…

    Java 2023年6月15日
    00
  • Java计时器工具StopWatch的具体使用

    首先需要了解的是,Java计时器工具StopWatch是一个简洁、轻量级的工具,它可以用来统计代码块、方法或程序的执行时间。下面我将详细讲解它的具体使用过程: 引入StopWatch 使用StopWatch的第一步是需要引入它所在的包,具体代码如下: import org.apache.commons.lang3.time.StopWatch; 其中,org…

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