spring-security用户登录逻辑验证接口org.springframework.security.core.userdetails.UserDetailsService只有一个方法
UserDetails loadUserByUsername(String username) throws UsernameNotFoundException;
UserDetail信息如下:我们自定义的用户信息要实现这个接口,
public interface UserDetails extends Serializable {
//权限相关
Collection extends GrantedAuthority> getAuthorities();
//获取密码
String getPassword();
//获取用户名
String getUsername();
//账户是否验证过期
boolean isAccountNonExpired();
//账户是否锁定
boolean isAccountNonLocked();
//账户验证是否过期
boolean isCredentialsNonExpired();
//账户是否有效
boolean isEnabled();
}
org.springframework.security.core.userdetails.User这个是它的一个实现
this.authorities = Collections.unmodifiableSet(sortAuthorities(authorities));//线程安全的权限添加 同时有内部类自定义排序
配置了这个Bean
以后,从前端传递过来的密码就会被加密,所以从数据库查询到的密码必须是经过加密的,而这个过程都是在用户注册的时候进行加密的。这就合理解释了为什么对上面的代码进行加密了。
org.springframework.security.crypto.password.PasswordEncoder
public interface PasswordEncoder { //加密 String encode(CharSequence var1); //验证是否匹配 boolean matches(CharSequence var1, String var2); }
在浏览器权限配置类BrowserSecurityConfig中注入这个bean
/**
* 浏览器security配置类
*
* @author CaiRui
* @date 2018-12-4 8:41
*/
@Configuration
public class BrowserSecurityConfig extends WebSecurityConfigurerAdapter {
/**
* 密码加密解密
* @return
*/
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http.
//spring5后默认就是表单登录方式
// httpBasic().
formLogin().
and().
authorizeRequests().
anyRequest().
authenticated();
}
}
package com.rui.tiger.auth.browser.user;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.authority.AuthorityUtils;
import org.springframework.security.core.userdetails.User;
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 CaiRui
* @date 2018-12-5 8:19
*/
@Component
@Slf4j
public class MyUserDetailServiceImpl implements UserDetailsService {
@Autowired
private PasswordEncoder passwordEncoder;
/**
* @param username
* @return
* @throws UsernameNotFoundException
*/
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
//TODO 后续做成数据库实现(MyBaites-plus实现)先实现流程
//1.根据用户名去数据库去查询用户信息获取加密后的密码 这里模拟一个加密的数据库密码
String encryptedPassWord = passwordEncoder.encode("123456");
log.info("模拟加密后的数据库密码:{}",encryptedPassWord);
//2.这里可以去验证账户的其它相关信息 默认都通过
//3.返回认证过的用户信息 授予一个admin的权限
return new User(username,
encryptedPassWord,
true,
true,
true,
true,
AuthorityUtils.commaSeparatedStringToAuthorityList("admin"));
}
}
实现完了我们启动项目来验证下配置的MyUserDetailServiceImpl是否成功了,可以看到默认的随机密码在控制台已经没有了。浏览器随便访问一个地址,会调到默认的登录表单界面
密码我们先随便输入一个 比如66666
可以看到登录失败,我们再输入我们固定的密码123456
可以看到我们登录成功,所以出现这个界面是因为http://localhost:8070/user这个我没有实现,验证成功后重定向到之前的地址 同时我们可以看到控制台也会打印如下信息 证明我们的自定义认证成功。ok下面我们开始实现自己的个性化登录需求开发
在实际开发中通常我们都不会使用spring-security默认的登录界面,我们可以通过配置实现自己的个性化登录,下面是具体实现。
1)自定义登录页面
首先修改我们的浏览器配置类BrowserSecurityConfig,同时要在资源文件下添加我们的自定义登录界面/tiger-login.html
package com.rui.tiger.auth.browser.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
/**
* 浏览器security配置类
*
* @author CaiRui
* @date 2018-12-4 8:41
*/
@Configuration
public class BrowserSecurityConfig extends WebSecurityConfigurerAdapter {
/**
* 密码加密解密
*
* @return
*/
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.formLogin()
.loginPage("/tiger-login.html")//自定义标准登录界面
.and()
.authorizeRequests()
.antMatchers("/tiger-login.html")//此路径放行 否则会陷入死循环
.permitAll()
.anyRequest()
.authenticated();
}
}
tiger-login.html文件如下,注意放置的路径
标准登录页面
标准登录页面
表单登录
ok 我们来启动项目输入http://localhost:8070/user 看看效果,可以看见已经成功跳到我们的自定义界面了
我们再次输入用户名user和密码123456试试看
可以看见又重定向到我们的tiger-login.html,这是怎么回事呢?
原来是是我们的 tiger-login.html定义的表单请求