Spring Security自定义用户认证过程(2)

我的实例是Spring Boot项目,随便一个SpringBoot项目都可以,先不启用SpringSecurity。

创建一个demoController,加方法:

```

@ResponseBody

@RequestMapping("wtf")

public String wtf(){

return "WTF";

}

```

运行项目,浏览器测试一下:

![image.png](/img/bVc40GG)

然后,pom文件加入SpringSecurity的依赖后就启用SpringSecurity了。

```

<dependency>

<groupId>org.springframework.boot</groupId>

<artifactId>spring-boot-starter-security</artifactId>

</dependency>

```

重新启动项目,访问wtf测试一下:

![image.png](/img/bVc40GJ)

说明SpringSecurity起作用了,由于Spring Security的默认安全策略是对所有请求都必须通过安全验证,所以请求wtf需要首先通过身份认证才能访问。这个时候他用的是默认的叫InMemoryUserDetailsManager的用户信息管理器来完成我们上篇文章所说的用户管理工作的,他的默认用户为user,密码在启动的过程中打印在了控制台:

![image.png](/img/bVc40HB)

用这个用户名、密码试一下:

![image.png](/img/bVc40HC)

可以访问:

![image.png](/img/bVc40HD)

好的,我们开始干活。

#### 用户对象Userdetails

首先需要有用户对象,用户对象需要有用户名、密码,SpringSecurity要求用户对象实现接口:

org.springframework.security.core.userdetails。

代码如下,简单一点:

```

@Component

public class User implements UserDetails {

private String name;

private String password;

@Override

public Collection<? extends GrantedAuthority> getAuthorities() {

return null;

}

@Override

public String getPassword() {

return password;

}

@Override

public String getUsername() {

return name;

}

@Override

public boolean isAccountNonExpired() {

return true;

}

@Override

public boolean isAccountNonLocked() {

return true;

}

@Override

public boolean isCredentialsNonExpired() {

return true;

}

@Override

public boolean isEnabled() {

return true;

}

}

```

#### UserDetailsService

然后需要有我们自己的UserDetailsService。

创建一个用户service类、实现UserDetailsService接口的loadUserByUsername方法即可。

我们创建一个用户名 user,密码:123456的用户,表示当前系统用户只有一个user用户、密码为123456.

```

@Service

@Slf4j

public class MyUserDetailsService implements UserDetailsService {

@Override

public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {

log.info("Here we are in MyUserDetailsService====");

User user=new User();

user.setName("user");

user.setPassword("123456");

return user;

}

}

```

#### PasswordEncoder

实现密码解析器PasswordEncoder的encode、matches方法,这两个方法很好理解,encode是对密码明文进行加密的,返回加密后的密码密文,matches方法是用来验密的。

我们不研究加密算法,所以也就不加密了,实际应用的时候,项目中可以替换encode方法为加密算法即可。

```

@Service

public class MyPasswordEncoder implements PasswordEncoder {

@Override

public String encode(CharSequence rawPassword) {

return rawPassword.toString();

}

@Override

public boolean matches(CharSequence rawPassword, String encodedPassword) {

return encode(rawPassword).equals(encodedPassword);

}

}

```

强调一下,UserDetailsService和PasswordEncoder需要加注解@Service,目的是注入Spring Ioc容器。

重新启动项目,这个时候控制台不会再打印上面的那个随机密码串了。

访问wtf,要求登录:

![image.png](/img/bVc40HR)

录入user/123456:

![image.png](/img/bVc40HS)

登录成功了!

说明上面我们自己创建的UserDetailsService和PasswordEncoder已经开始工作了!!!

***目标已经实现,任务完成了!!!***

***会不会觉得太简单了点?***

简单分析一下我们自己实现的这两个类的生效原因。

Spring Security在初始化UsernamePasswordAuthenticationFilter的过程中会通过一个叫 InitializeUserDetailsManagerConfigurer的配置类来初始化我们上一篇文章说过的AuthenticationProvider,通过上一篇文章我们知道绝大部分的用户验证工作都是这个AuthenticationProvider完成的。

我们简单看一下InitializeUserDetailsManagerConfigurer的configure方法:

```

@Override

public void configure(AuthenticationManagerBuilder auth) throws Exception {

if (auth.isConfigured()) {

return;

}

UserDetailsService userDetailsService = getBeanOrNull(UserDetailsService.class);

if (userDetailsService == null) {

return;

}

PasswordEncoder passwordEncoder = getBeanOrNull(PasswordEncoder.class);

UserDetailsPasswordService passwordManager = getBeanOrNull(UserDetailsPasswordService.class);

DaoAuthenticationProvider provider = new DaoAuthenticationProvider();

provider.setUserDetailsService(userDetailsService);

if (passwordEncoder != null) {

provider.setPasswordEncoder(passwordEncoder);

}

if (passwordManager != null) {

provider.setUserDetailsPasswordService(passwordManager);

}

provider.afterPropertiesSet();

auth.authenticationProvider(provider);

}

```

方法不长,可以看到首先要到Spring Ioc容器中去获取UserDetailsService和PasswordEncoder,如果能获取到的话,就赋值给初始化好的AuthenticationProvider。

***由于我们创建的UserDetailsService和PasswordEncoder都已经通过注解注入到SpringIoc容器中了,所以,这里就能获取到。后续AuthenticationProvider在用户认证干活的时候能调用到我们创建的这两个对象就不奇怪了!***

上一篇 [Spring Security自定义用户认证过程(1)](https://segmentfault.com/a/1190000043101053)

下一篇 [Spring Security + JWT](https://segmentfault.com/a/1190000043129636)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值