自定义登陆逻辑
SpringSecurity支持通过配置文件的方式定义用户信息(账号密码和角色等),但这种方式有明显的缺点,那就是系统上线后,用户信息的变更比较麻烦。因此SpringSecurity还支持通过实现UserDetailsService接口的方式来提供用户认证授权信息,其应用过程如下:
第一步:定义security配置类
/**
* 由@Configuration注解描述的类为spring中的配置类,配置类会在spring
* 工程启动时优先加载,在配置类中通常会对第三方资源进行初始配置.
*/
@Configuration
public class SecurityConfig {
/**
* 定义SpringSecurity密码加密对象
* @Bean 注解通常会在@Configuration注解描述的类中描述方法,
* 用于告诉spring框架这个方法的返回值会交给spring管理,并spring
* 管理的这个对象起个默认的名字,这个名字与方法名相同,当然也可以通过
* @Bean注解起名字
*/
@Bean //对象名默认为方法名
//@Bean("bcryptPasswordEncoder")//bean对象名字为bcryptPasswordEncoder
public BCryptPasswordEncoder passwordEncoder(){
return new BCryptPasswordEncoder();
}
}
第二步:定义UserDetailService接口实现类,自定义登陆逻辑,
UserDetailService为SpringSecurity官方提供的登录逻辑处理对象,我们自己可以实现此接口,然后在对应的方法中进行登录逻辑的编写即可.
package com.cy.jt.security.service;
@Service
public class UserDetailServiceImpl implements UserDetailsService {
@Autowired
private BCryptPasswordEncoder passwordEncoder;
/**
* 当我们执行登录操作时,底层会通过过滤器等对象,调用这个方法.
* @param username 这个参数为页面输出的用户名
* @return 一般是从数据库基于用户名查询到的用户信息
* @throws UsernameNotFoundException
*/
@Override
public UserDetails loadUserByUsername(String username)
throws UsernameNotFoundException {
//1.基于用户名从数据库查询用户信息
//User user=userMapper.selectUserByUsername(username);
if(!"jack".equals(username))//假设这是从数据库查询的信息
throw new UsernameNotFoundException("user not exists");
//2.将用户信息封装到UserDetails对象中并返回
//假设这个密码是从数据库查询出来的
String encodedPwd=passwordEncoder.encode("123456");
//假设这个权限信息也是从数据库查询到的
//假如分配权限的方式是角色,编写字符串时用"ROLE_"做前缀
List<GrantedAuthority> grantedAuthorities =
AuthorityUtils.commaSeparatedStringToAuthorityList(
"ROLE_admin,ROLE_normal,sys:res:retrieve,sys:res:create");
//这个user是SpringSecurity提供的UserDetails接口的实现,用于封装用户信息
//后续我们也可以基于需要自己构建UserDetails接口的实现
User user=new User(username,encodedPwd,grantedAuthorities);
return user;
}
}
说明,这里的User对象会交给SpringSecurity框架,框架提取出密码信息,然后与用户输入的密码进行匹配校验.
第三步&