在上一节中授权是基于内存的授权。在实际生产中用户信息时存在数据库中的,所以在这里进行改造,用户信息不在代码写死;
第一步:修改配置类,注掉基于内存的配置
@EnableWebSecurity
@Configuration
public class webSecurityConfig extends WebSecurityConfigurerAdapter {
//密码编译比对方式
@Bean
public BCryptPasswordEncoder passwordEncoder(){
return new BCryptPasswordEncoder();
}
//访问路径配置
@Override
protected void configure(HttpSecurity http) throws java.lang.Exception {
//hasAuthority : 基于资源授权 hasRole:基于角色授权
http
.csrf().disable() //去除csrf攻击的配置,以便除get请求方式,其他请求方式也能访问接口
.authorizeRequests()
.antMatchers("/auth/hello").hasAuthority("resource_1") //给访问的地址加上资源权限限制,只有用户有这个资源访问权限时才能访问
.antMatchers("/auth/home").hasAuthority("resource_2")
.antMatchers("/auth/admin").hasAuthority("resource_3")
.antMatchers("/test/health").permitAll() //此路径不需要经过过认证,可以不登录直接请求;注意不要放在上面的代码之前不然上面代码会失效,带通配符的url顺序也要注意 如 auth/login 应该放在auth/**的前面,也就是范围越大的越在后面
.anyRequest().authenticated() //除配置的/test/health路径其他请求都需要认证
.and()
.formLogin() //允许表单登陆
.successForwardUrl("/sys/login") //自定义表单登陆成功后的跳转路径
.and()
.logout()
.logoutUrl("/sys/logOut");
}
//基于内存的用户配置
// @Override
// protected void configure(AuthenticationManagerBuilder auth) throws java.lang.Exception {
// //创建三个用户到内存中,并给他们分配角色
// auth.inMemoryAuthentication()
// .withUser("zhangsan").password(this.passwordEncoder().encode("123456")).roles("GUEST");
// auth.inMemoryAuthentication()
// .withUser("lisi").password(this.passwordEncoder().encode("123456")).roles("USER");
// auth.inMemoryAuthentication()
// .withUser("wangwu").password(this.passwordEncoder().encode("123456")).roles("USER","ADMIN");
// }
}
第二步:自定义一个实现类SpringDataUserDetailsServiceImpl 并实现security
的UserDetailsService
接口的loadUserByUsername
方法,security自带的登陆页面登陆时会自动进入此类的方法进行认证;
@Service
public class SpringDataUserDetailsServiceImpl implements UserDetailsService {
private static Logger logger = Logger.getLogger(SpringDataUserDetailsServiceImpl.class);
@Autowired
private UserDao userDao;
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
logger.info("++进入SpringDataUserDetailsServiceImpl++ username = "+username);
UserDo u = new UserDo();
u.setUserName(username);
//mybatis-plus查询数据库的用户
UserDo user = userDao.selectOne(new QueryWrapper<>(u));
logger.info("查询到的用户信息:"+user.toString());
if(Objects.isNull(user)){
//没有查到用户交给provider来抛异常
return null;
}
UserDetails userDetails = User
.withUsername(user.getUserName())
.password(user.getPassword())
.authorities("resource_1")
.build();
logger.info("++退出SpringDataUserDetailsServiceImpl++");
return userDetails;
}
}
第四步:测试;
登陆成功