Spring Security(二)

6 篇文章 0 订阅
4 篇文章 0 订阅

Spring Security(二)

注:凡是源码部分,我已经把英文注释去掉了,有兴趣的同学可以在自己项目里进去看看。?

定义用户认证逻辑

用户登录成功后,用户的信息会被 Security 封装在一个接口里(“UserDetailsService”)

UserDetailsService 源码:

public interface UserDetailsService {
   // UserDetails 封装的用户信息接口
   UserDetails loadUserByUsername(String username) throws UsernameNotFoundException;
}

处理密码加密解密

Spring Security 处理登录密码的是 PasswordEncoder 接口。

PasswordEncoder 源码:

public interface PasswordEncoder {
    
    // 用来把用户登录时传入的密码进行加密处理
	String encode(CharSequence rawPassword);
    
    // 用来判断加密后的密码和用户传入的代码是否匹配
	boolean matches(CharSequence rawPassword, String encodedPassword);

}

Security 为 PasswordEncoder 接口提供了默认的实现 BCryptPasswordEncoder ,在项目中配置上密码加解密如下:

@Configuration
public class BrowserSecurityConfig extends WebSecurityConfigurerAdapter {

    @Bean
    public PasswordEncoder passwordEncoder() {
        // Security 默认实现
        return new BCryptPasswordEncoder();
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        // 启用表单登陆
        http.formLogin()
            .and()
            // 对请求做授权
            .authorizeRequests()
            // 任何请求
            .anyRequest()
            // 都需要身份认证
            .authenticated();
    }
}

配置 UserDetailService 接口实现:

@Configuration
public class MyUserDetailsService implements UserDetailsService {

    private static final Logger log = LoggerFactory.getLogger(MyUserDetailsService.class);

    @Autowired
    private PasswordEncoder passwordEncoder;

    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        log.info("登录用户名 ={}", username);
        // 根据用户名查询用户信息(此处省略与数据库交互逻辑)
        // 下面的“User”对象是Security的,它实现了UserDetailsService接口
        List<GrantedAuthority> grantedAuthorities =
                AuthorityUtils.commaSeparatedStringToAuthorityList("admin");
        // 根据查找到的用户信息判断用户是否被冻结
        String encode = passwordEncoder.encode("123456");
        log.info("加密后的密码 ={}", encode);
        return new User(username, encode,
                true, true, true, true, grantedAuthorities);
    }

}

登录后,日志如下:

2019-01-10 01:22:10.946  INFO 6572 --- [nio-8081-exec-3] c.i.s.browser.MyUserDetailsService       : 登录用户名 =root
2019-01-10 01:22:11.074  INFO 6572 --- [nio-8081-exec-3] c.i.s.browser.MyUserDetailsService       : 加密后的密码 =$2a$10$8NCzA8f.T9vLijKnrI9BKOKVB53FB4esFG1QlaBT1Fmh2I5ITjRGm

由此可见,Security 默认的加解密接口实现中的密码加密并不是我们所熟悉的 MD5 ,如果想使用 MD5 加密,可自定义一个 PasswordEncoder 接口的实现类,如下:

/**
 * 自定义 PasswordEncoder 接口实现
 */
public class MyPasswordEncoder implements PasswordEncoder {
    @Override
    public String encode(CharSequence rawPassword) {
        String pwd = rawPassword.toString();
        return DigestUtil.md5Hex(pwd);
    }

    @Override
    public boolean matches(CharSequence rawPassword, String encodedPassword) {
        return this.encode(rawPassword).equalsIgnoreCase(encodedPassword);
    }
}
@Configuration
public class BrowserSecurityConfig extends WebSecurityConfigurerAdapter {

    @Bean
    public PasswordEncoder passwordEncoder() {
        // Security 自定义实现
        return new MyPasswordEncoder();
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        // 启用表单登陆
        http.formLogin()
            .and()
            // 对请求做授权
            .authorizeRequests()
            // 任何请求
            .anyRequest()
            // 都需要身份认证
            .authenticated();
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Spring Security提供了强大的身份认证和授权功能,但默认情况下只提供了一种单一的认证方式。如果你需要进行次认证,你可以按照以下步骤进行配置: 1. 创建一个自定义的AuthenticationProvider:你可以实现`AuthenticationProvider`接口创建一个自定义的认证提供者。在该实现中,你可以添加额外的认证逻辑,例如验证手机验证码、指纹等。 2. 配置Spring Security:在Spring Security的配置类中,注册你自定义的AuthenticationProvider。可以使用`AuthenticationManagerBuilder`的`authenticationProvider`方法来注册。例如: ```java @Configuration @EnableWebSecurity public class SecurityConfig extends WebSecurityConfigurerAdapter { @Autowired private CustomAuthenticationProvider customAuthenticationProvider; @Override protected void configure(AuthenticationManagerBuilder auth) throws Exception { auth.authenticationProvider(customAuthenticationProvider); } // 其他配置... } ``` 3. 实现次认证逻辑:在自定义的AuthenticationProvider中,实现`authenticate`方法来执行次认证逻辑。例如,你可以在该方法中调用其他认证接口或者验证用户输入的验证码等。如果认证成功,返回一个`Authentication`对象;如果认证失败,可以抛出`AuthenticationException`异常。 ```java @Component public class CustomAuthenticationProvider implements AuthenticationProvider { @Override public Authentication authenticate(Authentication authentication) throws AuthenticationException { // 次认证逻辑,例如验证手机验证码 // 如果认证成功,返回一个Authentication对象 // 如果认证失败,可以抛出AuthenticationException异常 } @Override public boolean supports(Class<?> authentication) { return authentication.equals(UsernamePasswordAuthenticationToken.class); } } ``` 以上是一个基本的实现示例,你可以根据你的具体需求进行相应的调整和扩展。通过自定义AuthenticationProvider,你可以实现多种不同的认证方式,以满足不同场景下的次认证需求。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值