三分钟快速上手SpringSecurity框架

导入依赖框架

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

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

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

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

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

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

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

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


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

        方式一: 

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

      <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 = ?)

    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();
        }
    
    }
    
  3. 此时用户信息就是去数据库查询的 (用户信息表 创建包含用户密码关键字段即可)

    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');

        方式二:

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

  2. 重写springSecurity 的几个组件

    1. UserDetailsService 用户信息查询接口(内部具体编写查询逻辑 )
      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 加解密工具
      
          // 不进行解密、直接对比
          @Bean
          public PasswordEncoder passwordEncoder() {
              return NoOpPasswordEncoder.getInstance();
          }
      

    3. UserDetail 用户信息
      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 验证流程
      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;
          }
      }
      
  3.  验证组件交给springSecurity (同数据源方式类似)

    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);
        }
    
    
    
    
    }
    

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

   // 非页面列表页可以无权限访问外、其他都需要验证
    @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();
    }

自定义登陆页面(成功失败页面)


    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
                .authorizeRequests()
                .antMatchers("/loginSuccess").permitAll()
                .anyRequest().authenticated().and()
                .formLogin()// 采用默认登陆页方式
                // 默认登陆页面
                .loginPage("/loginPage")
                // 对应 form 表单提交路径
                .loginProcessingUrl("/doLogin")
                // 成功
                .successHandler(authSuccessHandler)
                // 失败
                .failureHandler(authFailHandler)
                .permitAll()
                .and().csrf().disable().httpBasic()
        ;
    }




package com.bu.config;

import org.springframework.security.core.Authentication;
import org.springframework.security.web.authentication.AuthenticationSuccessHandler;
import org.springframework.stereotype.Component;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;

/**
 * @author haizhuangbu
 * @date 2024/5/16 13:36
 * @mark AuthSuccessHandler
 */
@Component
public class AuthSuccessHandler implements AuthenticationSuccessHandler {
    @Override
    public void onAuthenticationSuccess(HttpServletRequest httpServletRequest, HttpServletResponse response, Authentication authentication) throws IOException, ServletException {
        response.setContentType("application/json;charset=utf-8");
        PrintWriter writer = response.getWriter();
        writer.printf("{message:登陆成功}");
        writer.flush();
    }
}




package com.bu.config;

import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.authentication.AuthenticationFailureHandler;
import org.springframework.stereotype.Component;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;

/**
 * @author haizhuangbu
 * @date 2024/5/16 14:50
 * @mark AuthFailHandler
 */
@Component
public class AuthFailHandler implements AuthenticationFailureHandler {
    @Override
    public void onAuthenticationFailure(HttpServletRequest httpServletRequest, HttpServletResponse response, AuthenticationException e) throws IOException, ServletException {
        response.setContentType("application/json;charset=utf-8");
        PrintWriter writer = response.getWriter();
        writer.printf("{message:登陆失败}");
        writer.flush();
    }
}


详细配置思维导图

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值