springsecurity基于数据库中的用户信息实现登陆

springsecurity基于数据库中的用户信息实现登陆

springsecurity简介

Spring Security是一个基于Java的开源框架,用于在Java应用程序中提供身份验证和授权的安全性。它是构建安全性功能的强大框架,可用于保护Web应用程序、REST API和其他类型的后端服务。
Spring Security提供了一套全面的安全性特性,包括用户身份验证、访问控制、密码管理、会话管理和跨站点请求伪造(CSRF)防护等。它还支持多种认证方式,包括基于表单的身份验证、基于HTTP基本认证、基于OAuth和OpenID Connect等。使用Spring Security,可以轻松地将安全性集成到你的应用程序中。它提供了灵活的配置选项和可扩展的API,使你能够根据具体的需求来定制和实现安全性功能。此外,Spring Security还与其他Spring框架和技术无缝集成,如Spring Boot、Spring MVC和Spring Data等。

实现步骤

1. 创建一个用户实体类(User Entity),用于表示存储在数据库中的用户信息。该实体类应包含用户名、密码和角色等必要的属性。
2. 创建一个用户详细信息服务类(UserDetailsService),实现Spring Security提供的 `UserDetailsService` 接口。该类应该实现 `loadUserByUsername` 方法,用于根据用户名从数据库中加载用户详细信息。
3. 创建一个密码编码器(Password Encoder)用于对用户密码进行加密。Spring Security提供了多种密码编码器实现,如BCryptPasswordEncoder、PasswordEncoder等。
4. 在Spring Security的配置类中,通过继承 `WebSecurityConfigurerAdapter` 并覆写 `configure` 方法,进行安全配置。:
  - 使用 `.userDetailsService(userDetailsService)` 方法指定你实现的用户详细信息服务类。
  - 使用 `.passwordEncoder(passwordEncoder)` 方法指定你选择的密码编码器。
  - 使用 `.jdbcAuthentication()` 方法启用基于数据库的身份验证。
  - 使用 `.dataSource(dataSource)` 方法指定你的数据源,以便Spring Security可以连接到数据库。
5. 在登录页面的表单中,需要包含用户名和密码的输入字段,并将表单的提交地址指向Spring Security提供的默认登录地址( `/login` )。

具体实现:

用户详细信息服务类(UserDetailsService),实现Spring Security提供的 UserDetailsService 接口。该类应该实现 loadUserByUsername 方法,用于根据用户名从数据库中加载用户详细信息。

@Service
public class MyUserDetailServiceImpl implements UserDetailsService {

    @Autowired
    private SysUserService sysUserService;

    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        SysUser sysUser = sysUserService.getByUserName(username);//根据用户名查询数据;也可以直接用getone查询
        if (sysUser==null){//没有找打该用户
            throw new UsernameNotFoundException("账户或密码错误");
        }else if ("1".equals(sysUser.getStatus())){//该用户的Status状态为1
            throw new UserCountLockException("账户已经被封禁,请联系管理员!");//自定义异常
        }
        //因为这个函数规定返回的UserDetails类型,为了方便,我们返回其实现类
        return new User(sysUser.getUsername(),sysUser.getPassword(),getUserAuthority(sysUser.getId()));
    }

    private List<GrantedAuthority> getUserAuthority(Long id) {
        return new ArrayList<>();
    }
}

密码编码器(Password Encoder)用于对用户密码进行加密

//默认密码加密配置
    @Bean
    BCryptPasswordEncoder bCryptPasswordEncoder(){
        return new BCryptPasswordEncoder();
    }

在Spring Security的配置类中,通过继承 WebSecurityConfigurerAdapter 并覆写 configure 方法,进行安全配置。

@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Autowired
    private LoginSuccessHandler loginSuccessHandler;

    @Autowired
    private LoginFailureHandler loginFailureHandler;

    @Autowired
    private MyUserDetailServiceImpl myUserDetailService;

    // 定义白名单URL路径数组
    private static final String URL_WHITELIST[] = {
            "/login",
            "/logout",
            "/captcha",
            "/password",
            "/image/**",
            "/test/**"
    } ;

    //默认密码加密配置
    @Bean
    BCryptPasswordEncoder bCryptPasswordEncoder(){
        return new BCryptPasswordEncoder();
    }

    /**
     * 配置应用程序的安全规则
     * 开启跨域资源共享(CORS)功能,并关闭跨站请求伪造(CSRF)攻击防护
     * 配置登录相关设置
     * 禁用会话(session)的创建
     * 配置拦截规则
     * @param http HttpSecurity对象,用于配置应用程序的安全规则
     * @throws Exception 配置过程中可能抛出的异常
     */
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
                .cors() // 开启CORS功能(跨域)
                .and()
                .csrf().disable() // 关闭CSRF攻击防护
                .formLogin() // 配置登录相关设置
                .successHandler(loginSuccessHandler) // 自定义登录成功处理器
                .failureHandler(loginFailureHandler) // 自定义登录失败处理器
                // .and()
                // .logout() // 配置注销设置(如果需要)
                // .logoutSuccessHandler() // 自定义注销成功处理器(如果需要)
                .and()
                //session禁用配置
                .sessionManagement()
                .sessionCreationPolicy(SessionCreationPolicy.STATELESS) // 禁用会话的创建(无状态)
                .and()
                .authorizeRequests()
                .antMatchers(URL_WHITELIST).permitAll() // 白名单中的URL路径允许无需身份验证/permitAll放行所有
                .anyRequest().authenticated(); // 其他所有请求需要身份验证
    }

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

}

拓展

自定义的登陆成功处理器

在上述代码中有一个自定义的登陆成功处理器。具体代码可以参考如下:

@Component
public class LoginFailureHandler implements AuthenticationFailureHandler {
    /**
     * 登录失败处理器
     *
     * @param httpServletRequest HTTP请求
     * @param httpServletResponse HTTP响应
     * @param e 认证异常
     * @throws IOException IO异常
     * @throws ServletException Servlet异常
     */
    @Override
    public void onAuthenticationFailure(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, AuthenticationException e) throws IOException, ServletException {
        // 设置响应内容类型为JSON,并且编码为UTF-8
        httpServletResponse.setContentType("application/json;charset=UTF-8");
        ServletOutputStream outputStream = httpServletResponse.getOutputStream();
        // 获取认证异常的错误信息
        String message=e.getMessage();
        // 如果是BadCredentialsException异常,则将错误信息设置为"用户名或者密码错误!"
        if(e instanceof BadCredentialsException){
            message="用户名或者密码错误!";
        }
        // 将错误信息以JSON格式写入响应输出流中
        outputStream.write(JSONUtil.toJsonStr(R.error(message)).getBytes("UTF8"));
        outputStream.flush();
        outputStream.close();
    }
}
// 这段代码是一个登录失败处理器的实现类。当用户认证失败后,会执行该类中的onAuthenticationFailure方法。该方法的作用是在HTTP响应中返回认证失败的错误信息。
//         具体代码解释如下:
//         - 设置响应内容类型为JSON,并且编码为UTF-8。
//         - 获取HTTP响应的输出流。
//         - 获取认证异常的错误信息。
//         - 如果认证异常是BadCredentialsException类型,则将错误信息设置为"用户名或者密码错误!"。
//         - 将错误信息以JSON格式写入响应输出流中。
//         - 刷新输出流并关闭。
自定义的登陆失败处理器

@Component
public class LoginSuccessHandler implements AuthenticationSuccessHandler {
    /**
     * 登录成功处理器
     *
     * @param httpServletRequest HTTP请求
     * @param httpServletResponse HTTP响应
     * @param authentication 认证信息
     * @throws IOException IO异常
     * @throws ServletException Servlet异常
     */
    @Override
    public void onAuthenticationSuccess(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Authentication authentication) throws IOException, ServletException {
        // 设置响应内容类型为JSON,并且编码为UTF-8
        httpServletResponse.setContentType("application/json;charset=UTF-8");
        ServletOutputStream outputStream = httpServletResponse.getOutputStream();
        // 定义用户名
        String username="user";
        // 生成JWT令牌
        String token = JwtUtils.genJwtToken(username);
        // 将登录成功信息和令牌写入响应输出流中
        outputStream.write(JSONUtil.toJsonStr(R.ok("登录成功").put("authorization",token)).getBytes());
        outputStream.flush();
        outputStream.close();
    }
}
// 这段代码是一个登录成功处理器的实现类。当用户成功认证后,会执行该类中的onAuthenticationSuccess方法。该方法的作用是在HTTP响应中返回登录成功的信息和生成的JWT令牌。
//         具体代码解释如下:
//         - 设置响应内容类型为JSON,并且编码为UTF-8。
//         - 获取HTTP响应的输出流。
//         - 定义用户名为"user"(通常应该从认证信息中获取)。
//         - 调用JwtUtils类的genJwtToken方法生成JWT令牌。
//         - 将登录成功信息和令牌以JSON格式写入响应输出流中。
//         - 刷新输出流并关闭。
用户详细信息服务类(UserDetailsService)中的自定义异常
public class UserCountLockException extends AuthenticationException {
    public UserCountLockException(String msg, Throwable t) {
        super(msg, t);
    }

    public UserCountLockException(String msg) {
        super(msg);
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值