三分钟快速上手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();
    }

详细配置思维导图

相关推荐
不会敲代码19 小时前
手写 Mini React:从 JSX 到虚拟 DOM 再到 render,搞懂 React 底层原理
前端·javascript·react.js
你不是我我10 小时前
【Java 开发日记】HTTP3 性能更好,为什么内网微服务依然多用 HTTP2?HTTP2 内网优势是什么?
java·开发语言·微服务
雪碧聊技术10 小时前
大模型爆火!Java后端如何抓住Agent全栈开发的风口
java·大模型·agent·全栈开发
kyriewen10 小时前
你的代码仓库变成“毛线团”了?Monorepo 用 Turborepo 拆成“乐高积木”
前端·javascript·面试
身如柳絮随风扬10 小时前
你知道什么是 Ajax 吗?—— 从入门到原理,一篇彻底搞懂
前端·ajax·okhttp
旷世奇才李先生11 小时前
Vue3\+TypeScript 2026实战——企业级前端项目架构搭建与性能优化全指南
前端·架构·typescript
Beginner x_u11 小时前
前端八股整理(工程化 02)|CommonJS/ESM、Webpack Loader/Plugin 与Vite 对比
前端·webpack·node.js·plugin·loader
逻辑驱动的ken12 小时前
Java高频面试场景题25
java·开发语言·深度学习·面试·职场和发展
openKaka_12 小时前
createRoot 到底创建了什么:FiberRootNode 和 HostRootFiber 的初始化过程
前端·javascript·react.js
习明然12 小时前
UniApp开发体验感受总结
前端·uni-app