三分钟快速上手SpringSecurity框架

导入依赖框架

web 框架(spring-boot-starter-web)

java 复制代码
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

springSecurity 框架(spring-boot-starter-security)

java 复制代码
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-security</artifactId>
        </dependency>

导入框架之后、当前应用已经具备验证功能

用户名默认为user、密码为启动窗口打印信息

默认登陆页(存在问题、每次需要记录登录密码)

配置文件配置固定用户名、密码


自定义功能实现(用户信息从数据库获取)

方式一:

导入数据源依赖 mysql\mybatis,配置数据源信息

java 复制代码
  <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>8.0.28</version>
        </dependency>

        <dependency>
            <groupId>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter</artifactId>
            <version>2.1.3</version>
        </dependency>


2.

直接配置查询 sql (select username,password from s_usr where username = ?)

java 复制代码
package com.bu.config;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.password.NoOpPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;

import javax.sql.DataSource;

/**
 * @author haizhuangbu
 * @date 2024/5/15 16:35
 * @mark WebSecurityConfigImpl
 */
@Configuration
@EnableWebSecurity
public class WebSecurityConfigImpl extends WebSecurityConfigurerAdapter {

    @Autowired
    private DataSource dataSource;

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.jdbcAuthentication()
                // 配置数据源
                .dataSource(dataSource)
                // 查询sql
                .usersByUsernameQuery("select username,password,'Y' enabled from s_usr where username = ?")
                .authoritiesByUsernameQuery("select username,authority\n" +
                        "from authorizes where username = ?");
    }


    // 不进行解密、直接对比
    @Bean
    public PasswordEncoder passwordEncoder() {
        return NoOpPasswordEncoder.getInstance();
    }

}

此时用户信息就是去数据库查询的 (用户信息表 创建包含用户密码关键字段即可)

sql 复制代码
create table s_usr
(
    user_id     varchar(36) not null
        primary key,
    username    varchar(36) null,
    password    varchar(36) null,
    create_time datetime    null,
    modify_time datetime    null,
    enable      char(2)     null comment 'Y 生效 N 失效'
);



create table authorizes
(
    username  varchar(36),
    authority varchar(36)
);



insert into s_usr
values ('1', 'admin', 'admin', now(), now(), 'Y');

方式二:

导入数据源配置信息同方式一相同

重写springSecurity 的几个组件

  1. UserDetailsService 用户信息查询接口(内部具体编写查询逻辑 )

    sql 复制代码
    package com.bu.config;
    
    import com.bu.sys.user.dao.UserDetailsDao;
    import com.bu.sys.user.dto.SUsrDto;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.security.core.userdetails.UserDetails;
    import org.springframework.security.core.userdetails.UserDetailsService;
    import org.springframework.security.core.userdetails.UsernameNotFoundException;
    import org.springframework.stereotype.Component;
    
    /**
     * @author haizhuangbu
     * @date 2024/5/15 16:22
     * @mark AuthUserServiceImpl
     */
    @Component
    public class AuthUserServiceImpl implements UserDetailsService {
    
    
        @Autowired
        private UserDetailsDao userDetailsDao;
    
        @Override
        public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
            SUsrDto sUsrDto = userDetailsDao.findSUsrByUsername(username);
            return sUsrDto;
        }
    }
    
    
    
    package com.bu.sys.user.dao;
    
    import com.bu.sys.user.dto.SUsrDto;
    import org.apache.ibatis.annotations.Select;
    
    /**
     * @author haizhuangbu
     * @date 2024/5/15 17:15
     * @mark UserDetailsDao
     */
    public interface UserDetailsDao {
    
        @Select("select * from s_usr where username = #{username}")
        SUsrDto findSUsrByUsername(String username);
    
    }
  2. PasswordEncoder 加解密工具

    java 复制代码
        // 不进行解密、直接对比
        @Bean
        public PasswordEncoder passwordEncoder() {
            return NoOpPasswordEncoder.getInstance();
        }
  3. UserDetail 用户信息

    java 复制代码
    package com.bu.sys.user.dto;
    
    import org.springframework.security.core.GrantedAuthority;
    import org.springframework.security.core.userdetails.UserDetails;
    
    import java.util.Collection;
    
    /**
     * @author haizhuangbu
     * @date 2024/5/15 17:16
     * @mark SUsrDto
     */
    public class SUsrDto implements UserDetails {
    
        private String username;
    
        private String password;
    
    
        public String getUsername() {
            return username;
        }
    
        @Override
        public boolean isAccountNonExpired() {
            return true;
        }
    
        @Override
        public boolean isAccountNonLocked() {
            return true;
        }
    
        @Override
        public boolean isCredentialsNonExpired() {
            return true;
        }
    
        @Override
        public boolean isEnabled() {
            return true;
        }
    
        public void setUsername(String username) {
            this.username = username;
        }
    
        @Override
        public Collection<? extends GrantedAuthority> getAuthorities() {
            return null;
        }
    
        public String getPassword() {
            return password;
        }
    
        public void setPassword(String password) {
            this.password = password;
        }
    }
  4. AuthenticationProvider 验证流程

    java 复制代码
    package com.bu.config;
    
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.security.authentication.AuthenticationProvider;
    import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
    import org.springframework.security.core.Authentication;
    import org.springframework.security.core.AuthenticationException;
    import org.springframework.security.core.userdetails.UserDetails;
    import org.springframework.security.core.userdetails.UserDetailsService;
    import org.springframework.security.core.userdetails.UsernameNotFoundException;
    import org.springframework.security.crypto.password.PasswordEncoder;
    import org.springframework.stereotype.Component;
    
    /**
     * @author haizhuangbu
     * @date 2024/5/15 17:20
     * @mark UserAutorizedServiceImpl
     */
    @Component
    public class UserAuthorizedServiceImpl implements AuthenticationProvider {
    
        @Autowired
        private UserDetailsService userDetailsService;
    
    
        @Autowired
        private PasswordEncoder passwordEncoder;
    
        @Override
        public Authentication authenticate(Authentication authentication) throws AuthenticationException {
    
            // 查询用户信息
            UserDetails userDetails = userDetailsService.loadUserByUsername(authentication.getName());
    
            if (userDetails == null) {
                throw new UsernameNotFoundException("用户信息不存在");
            }
    
    
            if (!passwordEncoder.matches(userDetails.getPassword(), (String) authentication.getCredentials())) {
    
                throw new UsernameNotFoundException("密码不正确");
    
            }
    
            return new UsernamePasswordAuthenticationToken(userDetails.getUsername(), userDetails.getPassword());
        }
    
        @Override
        public boolean supports(Class<?> aClass) {
            return true;
        }
    }

验证组件交给springSecurity (同数据源方式类似)

java 复制代码
package com.bu.config;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.password.NoOpPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;

import javax.sql.DataSource;

/**
 * @author haizhuangbu
 * @date 2024/5/15 16:35
 * @mark WebSecurityConfigImpl
 */
@Configuration
@EnableWebSecurity
public class WebSecurityConfigImpl extends WebSecurityConfigurerAdapter {

    @Autowired
    private UserAuthorizedServiceImpl userAuthorizedService;

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




}

配置其他信息(成功跳转、失败跳转....)

java 复制代码
   // 非页面列表页可以无权限访问外、其他都需要验证
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests()
                // permitAll 放行路径
                .antMatchers("/login", "/blogs/listAllBlogs", "/blogs/listBloggerInfo", "/theme/listAll")
                .permitAll()
                .anyRequest().authenticated()
                .and().formLogin() // 默认 login 登陆路径
                .failureHandler(failLoginHandler)// 成功处理逻辑
//                .defaultSuccessUrl("/success")
//                .failureUrl("/error")
                .and().addFilterAfter(tokenFilter, BasicAuthenticationFilter.class)
        ;

        http.csrf().disable();

        http.cors().disable();
    }

详细配置思维导图

相关推荐
打野赵怀真14 分钟前
render函数中return如果没有使用()会有什么问题?
前端·javascript
Riesenzahn16 分钟前
写一个左中右的满屏布局,左右固定220px,中间自适应并且要优先加载
前端·javascript
Riesenzahn16 分钟前
css在页面上画一个正方形,边长为页面宽度的一半
前端·javascript
tommyrunner18 分钟前
Cursor rule文件测试 一秒了解AI行为规则文件
前端·cursor
FreemanGordon22 分钟前
Java volatile 关键字
java
北京_宏哥23 分钟前
《手把手教你》系列基础篇(九十三)-java+ selenium自动化测试-框架设计基础-POM设计模式实现-上篇(详解教程)
java·前端·selenium
Nu1128 分钟前
weakMap 和 weakSet 原理
前端·面试
顾林海30 分钟前
深入理解 Dart 函数:从基础到高阶应用
android·前端·flutter
北京_宏哥31 分钟前
《手把手教你》系列基础篇(九十二)-java+ selenium自动化测试-框架设计基础-POM设计模式简介(详解教程)
java·selenium·前端工程化