1.springsecurity配置
对于springsecurity的配置要扩展继承WebSecurityConfigurerAdapter方法,主要有两个任务,一个是配置密码的加密方式,第二个是配置身份验证。通过配置身份验证,spring security身份验证可以通过过滤拦截,验证客户端的身份的有效性,并返回赋予其权限。
/**
* WebSecurityConfigurerAdapter中有相当多的springsecurity默认配置,如果需要自定义其中的配置需要进行对它扩展
*/
@Configuration
public class ProjectConfig extends WebSecurityConfigurerAdapter {
@Autowired
private AuthenticationProviderService authenticationProvider;
/**
* PasswordEncoder 承担两个任务:
* 1. 将密码进行编码
* 2。 验证密码是否与现有编码相匹配
*
* NoOpPasswordEncoder 实例会将密码视为普通文本。不会对密码进行加密或者哈希操作。为了进行匹配,NoOpPasswordEncoder
* 只会使用String类底层的equals(Object o)方法来比较字符串。所以,不应该在生产环境中使用该方式。
*/
@Bean
public BCryptPasswordEncoder bCryptPasswordEncoder() {
return new BCryptPasswordEncoder();
}
@Bean
public SCryptPasswordEncoder sCryptPasswordEncoder() {
return new SCryptPasswordEncoder();
}
@Override
protected void configure(AuthenticationManagerBuilder auth) {
auth.authenticationProvider(authenticationProvider);
}
@Override
protected void configure(HttpSecurity http) throws Exception {
//todo:
/**
* 身份验证方式,表单验证方式。
*
* 在客户端访问时,要附加前缀Basic,后面还要加上包含用户名和密码的字符串Base64编码,用冒号(:)分隔。
*/
http.formLogin()
//登录成功后跳转到主页面
.defaultSuccessUrl("/main", true);
http.authorizeRequests().anyRequest().authenticated();
}
}
2.UserDetails用户的详细描述
在springsecurity中该类继承 UserDetails用于描述用户的密码权限等内容,在过身份验证滤拦截器中拿到该类的信息进行对账号密码的比对,同时提取权限信息用于赋予登录客户端的权限信息。
@Data
public class CustomUserDetails implements UserDetails {
//note: 为了说明没有User实体CustomUserDetails就毫无意义,所以将该字段用final修饰
private final User user;
public CustomUserDetails(User user) {
this.user = user;
}
@Override
public Collection<? extends GrantedAuthority> getAuthorities() {
return user.getAuthorities().stream()
//将在数据库中找到的该用户的每个权限名称映射到一个SimpleGrantedAuthority
.map(a -> new SimpleGrantedAuthority(a.getName()))
//以列表形式收集并返回 SimpleGrantedAuthority的所有实例
.collect(Collectors.toList());
}
@Override
public String getPassword() {
return user.getPassword();
}
@Override
public String getUsername() {
return user.getUsername();
}
@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 final User getUser() {
return user;
}
}
3.loadUserByUsername加载用户信息
loadUserByUsername是UserDetailsService抽象类中的一个方法,通过继承实现该方法达到获取用户信息描述(UserDetails)的能力,随后进行对账号密码的比对。
@Override
public CustomUserDetails loadUserByUsername(String username) {
//创建一个异常类
Supplier<UsernameNotFoundException> s =
() -> new UsernameNotFoundException("Problem during authentication!");
//如果返回为空,则返回异常类。如果查询的到则返回User对象。
User u = userRepository.findUserByUsername(username).orElseThrow(s);
return new CustomUserDetails(u);
}
4.authenticate 截取陌生客户端的鉴权信息(账号密码)
@Override
public Authentication authenticate(Authentication authentication) throws AuthenticationException {
String username = authentication.getName();
String password = authentication.getCredentials().toString();
/**
* 使用UserDetailsService (JpaUserDetailsService实现UserDetailsService)
* 的loadUserByUsername方法查询用户详细信息
*/
CustomUserDetails user = userDetailsService.loadUserByUsername(username);
switch (user.getUser().getAlgorithm()) {
case BCRYPT:
return checkPassword(user, password, bCryptPasswordEncoder);
case SCRYPT:
return checkPassword(user, password, sCryptPasswordEncoder);
}
throw new BadCredentialsException("Bad credentials");
}
@Override
public boolean supports(Class<?> aClass) {
return UsernamePasswordAuthenticationToken.class.isAssignableFrom(aClass);
}
5.checkPassword 比对账号密码并返回权限
/**
* 核对密码
* @param user 查询的人员信息
* @param rawPassword 密码
* @param encoder 编码方式
* @return
*/
private Authentication checkPassword(CustomUserDetails user, String rawPassword, PasswordEncoder encoder) {
if (encoder.matches(rawPassword, user.getPassword())) {
return new UsernamePasswordAuthenticationToken(user.getUsername(), user.getPassword(), user.getAuthorities());
} else {
throw new BadCredentialsException("Bad credentials");
}
}
6. 完整代码
6.1 代码目录
6.2 代码下载
整理好后会附上链接