公告

👇公众号👇---👇 微信 👇

欢迎大家加群&私信交流

文章首/文尾有群二维码

Skip to content

springSecurity-1

1. 创建项目

1.1 选择基础的依赖

create-project

1.2 创建测试接口

create-test-interface

1.3 配置springSecurity账号密码

configure-springSecurity-account-password

1.4 账号密码的由来

idea中搜索SecurityProperties.class account-password-source

2. SpringSecurity配置类

定义用户名和密码

基于内存的用户名和密码,角色的定义,后边切换为数据库,目的在于搞明白springSecurity认证流程

java
/**
 * @author cute050
 * @createTime 2024年11月05日 10:32
 * @description
 * 使用的是spring Security 6.X.X 版本
 * 1. 不需要继承其他的Security类
 * 2. 需要使用@Configuration 才会被spring容器加载
 * 3. 废弃了很多方法 比如and()方法,建议使用lambda表达式实现
 */
@Configuration
@EnableWebSecurity // 启动spring Security自定义配置
public class SecurityConfig {

    // 自定义用户名和密码
    @Bean
    public UserDetailsService userDetailsService() {
        // 定义用户信息
        UserDetails adminUser = User.withUsername("admin")
                .password("{noop}123456")
                .roles("admin", "user")
                .build();

        UserDetails vipUser = User.withUsername("user")
                .password("{noop}123456")
                .roles( "user")
                .build();
        // 将用户存储到spring Security中
        InMemoryUserDetailsManager userDetailsManager = new InMemoryUserDetailsManager();
        // 创建两个用户
        userDetailsManager.createUser(adminUser);
        userDetailsManager.createUser(vipUser);
        return userDetailsManager;
    }
}

InMemoryUserDetailsManager-loadUserByUsername

密码加密

java
    @Bean
    public PasswordEncoder passwordEncoder(){
        // 构建密码编辑器
        return new BCryptPasswordEncoder();
    }

测试类

java
/**
 * @author cute050
 * @createTime 2024年11月05日 12:30
 * @description
 */
@SpringBootTest
public class myTest {

    @Autowired
    private PasswordEncoder passwordEncoder;

    @Test
    public void test(){
        String pass = "123456";
        String result = passwordEncoder.encode(pass);
        System.out.println("result====> " + result);
        // 匹配密码
        boolean matches = passwordEncoder.matches(pass, result);
        System.out.println("matches====> " + matches);
    }
}

3. 自定义登录页面

使用thymeleaf模板引擎实现

3.1 创建登录页面

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

3.2 创建登录页面

html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>自定义的登录页面</title>
</head>
<body>
<form th:action="@{/doLogin}" method="post">
    用户名: <input name="username" placeholder="请输入用户名"> <br/>
    密码: <input name="password" placeholder="请输入密码" type="password"> <br/>
    <input type="submit" value="登录">
</form>
</body>
</html>
html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>首页</title>
</head>
<body>
恭喜你 登录成功!
</body>
</html>
java
@GetMapping("/toLogin")
public String toLogin(){
    System.out.println("跳转到登录页面");
    return "login";
}

@GetMapping("/index")
public String index(){
    return "index";
}
java
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
    // 配置关闭csrf
    http.csrf(AbstractHttpConfigurer::disable)
            .authorizeHttpRequests(auth ->
                    auth.requestMatchers("/toLogin")
                            .permitAll()
                            .anyRequest()
                            .authenticated())
            .formLogin(form -> form.loginPage("/toLogin") // 跳转到自定义的登录页面
                    .loginProcessingUrl("/doLogin")  // 处理前端请求 与form表单的action一致
                    .usernameParameter("username")
                    .passwordParameter("password")
                    .defaultSuccessUrl("/index") // 请求到index页面
            );
    return http.build();
}
yml
spring:
  security:
    user:
      name: admin
      password: 123456

4. 基于请求的授权

java
http.csrf(AbstractHttpConfigurer::disable)
        .authorizeHttpRequests(auth ->
                auth
//                                .requestMatchers("/test1").hasRole("admin")
//                                .requestMatchers("/test1").hasAnyRole("admin", "user")
                        .requestMatchers("/test1").hasAuthority("test1:show")
                        .requestMatchers("/toLogin")
                        .permitAll()
                        .anyRequest()
                        .authenticated())
        .formLogin(form -> form.loginPage("/toLogin") // 跳转到自定义的登录页面
                .loginProcessingUrl("/doLogin")  // 处理前端请求 与form表单的action一致
                .usernameParameter("username")
                .passwordParameter("password")
                .defaultSuccessUrl("/index") // 请求到index页面
        );
return http.build();
}

@Bean
public UserDetailsService userDetailsService() {
    // 定义用户信息
    UserDetails adminUser = User.withUsername("admin")
            .password("$2a$10$3oAw9LES8Kw2UAHR.59aEe0MELHzeyjBPZvzQoFbYvHJ.UvfbjnKi")
            .roles("admin")
            .build();

    UserDetails vipUser = User.withUsername("user")
            .password("$2a$10$3oAw9LES8Kw2UAHR.59aEe0MELHzeyjBPZvzQoFbYvHJ.UvfbjnKi")
            .roles("user")
            .build();
    // 将用户存储到spring Security中
    InMemoryUserDetailsManager userDetailsManager = new InMemoryUserDetailsManager();
    // 创建两个用户
    userDetailsManager.createUser(adminUser);
    userDetailsManager.createUser(vipUser);
    return userDetailsManager;
}

@Bean
public PasswordEncoder passwordEncoder() {
    // 构建密码编辑器
    return new BCryptPasswordEncoder();
}

request-authorization

5. 基于方法鉴权

在SpringSecurity6版本中@EnableGlobalMethodSecurity被弃用,取而代之的是@EnableMethodSecurity。默认情况下,会激活pre-post注解,并在内部使用AuthorizationManager。

新老API区别

此@EnableMethodSecurity替代了@EnableGlobalMethodSecurity。提供了以下改进:

使用简化的AuthorizationManager。 支持直接基于bean的配置,而不需要扩展GlobalMethodSecurityConfiguration 使用Spring AOP构建,删除抽象并允许您使用Spring AOP构建块进行自定义 检查是否存在冲突的注释,以确保明确的安全配置 符合JSR-250 默认情况下启用@PreAuthorize、@PostAuthorize、@PreFilter和@PostFilter