SpringBoot + Spring Security 基本使用及个性化登录配置详解

SpringBoot+SpringSecurity基本使用

1. 引入Spring Security

在pom.xml中添加Spring Security的依赖:

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

2. 编写SecurityConfig

创建一个继承自WebSecurityConfigurerAdapter的配置类,用于配置Spring Security相关内容。代码如下:

@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
    @Autowired
    private UserDetailsService userDetailsService;

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

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

在上面的代码中,我们首先通过@EnableWebSecurity注解开启Web Security。然后,我们使用@Autowired注解将UserDetailsService注入到配置类中,UserDetailsService用于根据用户名获取用户信息。在configure方法中,我们将UserDetailsService传递给AuthenticationManagerBuilder,并使用passwordEncoder方法返回的PasswordEncoder对象对密码进行加密。PasswordEncoder用于加密用户密码。

3. 编写登录页

创建一个Controller,并在其中定义返回登录页面的方法。代码如下:

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

在上述示例中,我们使用了@GetMapping注解定义了一个GET请求。

4. 配置登录认证

我们需要创建一个实现UserDetailsService接口的类,并定义用于获取用户信息的方法。代码如下:

@Service
public class UserDetailsServiceImpl 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 user;
    }
}

在上面的代码中,我们通过@Service注解将UserDetailsServiceImpl注入到Spring容器中。然后,我们实现loadUserByUsername方法,该方法用于根据用户名查询用户信息。

5. 配置访问控制

我们可以通过方法authorizeRequests配置访问权限。代码如下:

@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests()
                .antMatchers("/login", "/register").permitAll()
                .anyRequest().authenticated()
                .and()
                .formLogin().loginPage("/login").defaultSuccessUrl("/").permitAll()
                .and()
                .logout().permitAll();
    }

    @Autowired
    private UserDetailsService userDetailsService;

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

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

在上述示例中,我们定义了两个不需要授权即可访问的URL:/login/register。对于其他任何URL,用户必须先进行验证才能访问。在formLogin配置中,我们使用了loginPage方法指定了自定义的登录页面,通过defaultSuccessUrl方法配置默认成功跳转的URL。在logout配置中,我们允许用户进行注销操作。

SpringSecurity个性化登录配置详解

1. 美化登录页面

可以通过在resources/static下放置login.html文件,然后在SecurityConfig配置中配置loginPage方法指向该页面,从而实现美化登录页面的目的。

2. 自定义验证身份逻辑

我们可以通过传入一个AuthenticationProvider对象,使用自定义校验逻辑,该类需要实现AuthenticationProvider接口。示例代码如下:

@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.authenticationProvider(new AuthenticationProvider() {
            @Override
            public Authentication authenticate(Authentication authentication) throws AuthenticationException {
                String username = authentication.getName();
                String password = authentication.getCredentials().toString();
                if ("admin".equals(username) && "123456".equals(password)) {
                    List<GrantedAuthority> grantedAuthorities = new ArrayList<>();
                    grantedAuthorities.add(new SimpleGrantedAuthority("ROLE_ADMIN"));
                    return new UsernamePasswordAuthenticationToken(authentication.getPrincipal(), authentication.getCredentials(), grantedAuthorities);
                } else {
                    throw new BadCredentialsException("用户名或密码错误");
                }
            }

            @Override
            public boolean supports(Class<?> aClass) {
                return true;
            }
        });
    }
}

在上面的代码中,我们自定义了一个AuthenticationProvider对象,该对象实现了authenticate方法,该方法用于验证用户身份是否正确。如果用户名和密码正确,我们返回一个UsernamePasswordAuthenticationToken对象,该对象保存了用户的认证信息。否则,我们抛出一个BadCredentialsException异常,该异常用于表示认证失败的情况。

3. 多方式登录

我们可以通过配置多个AuthenticationProvider对象,实现多种登录方式。示例代码如下:

@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        DaoAuthenticationProvider daoAuthenticationProvider = new DaoAuthenticationProvider();
        daoAuthenticationProvider.setUserDetailsService(userDetailsService());
        daoAuthenticationProvider.setPasswordEncoder(passwordEncoder());

        auth.authenticationProvider(daoAuthenticationProvider);

        InMemoryAuthenticationProvider inMemoryAuthenticationProvider = new InMemoryAuthenticationProvider();
        inMemoryAuthenticationProvider.setUserDetailsService(userDetailsService());
        inMemoryAuthenticationProvider.setPasswordEncoder(passwordEncoder());

        auth.authenticationProvider(inMemoryAuthenticationProvider);
    }
}

在上述示例中,我们配置了一个DaoAuthenticationProvider(数据库验证)和一个InMemoryAuthenticationProvider(内存验证)。如果第一个AuthenticationProvider对象无法验证通过,Spring Security会尝试通过第二个AuthenticationProvider验证。

4. 自定义登录成功后跳转的页面

我们可以使用defaultSuccessURL方法指定成功之后的跳转页面。示例代码如下:

@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.formLogin()
            .loginPage("/login").permitAll()
            .defaultSuccessUrl("/")
            .and()
            .logout().permitAll();
    }
}

在上述示例中,我们使用了defaultSuccessURL方法指定成功之后的跳转页面为根目录/。当登录成功之后,用户将会被跳转到根目录页面。

5. 登录成功之后返回JSON

我们可以将登录成功之后返回JSON数据,示例代码如下:

@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.formLogin()
            .successHandler((request, response, authentication) -> {
                response.setContentType("application/json;charset=UTF-8");
                PrintWriter out = response.getWriter();
                out.write("{\"status\":\"success\", \"msg\":\"登录成功\"}");
                out.flush();
                out.close();
            })
            .failureHandler((request, response, exception) -> {
                response.setContentType("application/json;charset=UTF-8");
                PrintWriter out = response.getWriter();
                out.write("{\"status\":\"error\", \"msg\":\"登录失败\"}");
                out.flush();
                out.close();
            });
    }
}

在上述示例中,我们将JSON数据写入到HttpServletResponse中,并通过setContentType方法设置了返回数据的类型为json。在登录失败的情况下,我们也执行了类似的操作。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:SpringBoot + Spring Security 基本使用及个性化登录配置详解 - Python技术站

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

相关文章

  • Spring Security动态权限的实现方法详解

    Spring Security动态权限的实现方法详解 Spring Security 是一个基于 Spring 的安全框架,提供了一种基于角色的访问控制模型。但是在一些场景中,我们需要动态地控制用户的权限,这时候我们就需要实现 Spring Security 的动态权限控制。本文将详细介绍如何实现 Spring Security 动态权限的控制。 实现步骤 …

    Java 2023年6月3日
    00
  • jdk1.8 LocalTime、LocalDate、LocalDateTime 使用大全

    目录 LocalTime、LocalDate、LocalDateTime 区别 LocalTime、LocalDate、LocalDateTime 使用 now 获取当前 时刻、日期、时间 of 获取指定 时刻、日期、时间 plus || minus 增加或者减少 更改指定的 时间 isAfter || isBefore 比较大小 compareTo 时间比…

    Java 2023年4月22日
    00
  • MyBatis批量插入的五种方式小结(MyBatis以集合方式批量新增)

    MyBatis批量插入的五种方式小结 在使用MyBatis进行批量插入时,有多种方式可以选择。本文将介绍MyBatis批量插入的五种方式,并提供示例代码,以便读者更好地理解这些方法。 方式一:使用for循环单条插入 在使用for循环单条插入时,需要在for循环中执行insert语句。这种方式的优点是插入的数据可以轻松地进行转换,缺点是插入效率较低。 priv…

    Java 2023年6月1日
    00
  • Java8中stream和functional interface的配合使用详解

    下面我将给出一个详细讲解“Java8中stream和functional interface的配合使用”的攻略: 一、什么是stream和functional interface 1.1 stream 在Java中,Stream是Java 8提供的一个新特性。Stream提供了一种更便捷的方式来处理集合数据,可以实现很多操作,比如过滤,排序和统计等。Stre…

    Java 2023年5月26日
    00
  • java定义数组的三种类型总结

    Java定义数组的三种类型 在 Java 中,定义数组有三种类型:一维数组、二维数组和不规则数组。这篇攻略将详细介绍这三种类型的定义方式及注意事项。 一维数组 一维数组是最常见的数组类型,可以理解为一个线性的排列方式。Java 中定义一维数组的方式如下: // 定义一个 int 类型的一维数组 int[] array1 = new int[5]; // 定义…

    Java 2023年5月26日
    00
  • 通过spring用beanshell实现java接口示例

    通过Spring使用Beanshell实现Java接口的过程如下: 准备工作 首先,确保安装了Beanshell和Spring依赖项。在此过程中,我们将使用Gradle作为构建工具。在项目的build.gradle文件中添加以下代码,然后运行gradle build以加载所需的依赖项: dependencies { … compile ‘org.spri…

    Java 2023年6月15日
    00
  • SpringMVC接收前台传递过来的值的实例

    下面我来详细讲解“SpringMVC接收前台传递过来的值的实例”的完整攻略。 1. 前置条件 在开始之前,需要保证你已经: 安装了Java开发环境(JDK) 安装了Spring框架 2. 实例1:接收表单数据 假设我们有一个表单页面,其中包含一个输入框和一个提交按钮,我们需要在后台接收前台传递过来的输入框的值。以下是实现过程: 在表单页面中,添加一个输入框和…

    Java 2023年6月15日
    00
  • java中list的用法和实例讲解

    下面是“java中list的用法和实例讲解”的完整攻略。 1. List的简介 List是Java中最常用的集合类型之一,它允许存储重复元素,并按照插入顺序维护元素的顺序。List接口是Collection接口的子接口。List接口有许多不同的实现方式,比如ArrayList、LinkedList等。 2. List的用法 2.1 创建List 创建List…

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