1、导入依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>org.thymeleaf.extras</groupId>
<artifactId>thymeleaf-extras-springsecurity5</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-test</artifactId>
<scope>test</scope>
</dependency>
2、自定义MyUserDetailService
要实现UserDetailsService
接口
@Service
public class MyUserDetailService implements UserDetailsService {
@Resource
MemberinfoMapper memberinfoMapper;
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
MemberinfoExample example = new MemberinfoExample();
MemberinfoExample.Criteria criteria = example.createCriteria();
criteria.andNicknameEqualTo(username);
List<Memberinfo> memberinfos = memberinfoMapper.selectByExample(example);
String name = memberinfos.get(0).getNickname();
String pwd = memberinfos.get(0).getPwd();
String role = memberinfos.get(0).getPhoto();
// 角色集合
List<GrantedAuthority> authorities = new ArrayList<>();
// 角色必须以`ROLE_开头,数据库中没有,则在这里加
authorities.add(new SimpleGrantedAuthority(role));
System.out.println("角色:"+memberinfos.get(0));
if (memberinfos.size()>0) { //数据库已经加密过了 不需要再加密了
return new User(name, pwd,
// role
authorities
// AuthorityUtils.commaSeparatedStringToAuthorityList(role)
);
}
else {
throw new UsernameNotFoundException("用户\""+username+"\"不存在!");
}
}
}
3、SecurityConfig(重点)
//AOP:拦截器
@EnableWebSecurity
@Configuration
@EnableGlobalMethodSecurity(prePostEnabled = true) // 开启方法级安全验证
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Resource
MyUserDetailService myUserDetailService; //第二部中我们自己定义的
//链式变成
//授权请求
@Override
protected void configure(HttpSecurity http) throws Exception {
//首页所有人可以访问 功能也只有对应权限的人才能访问
http.authorizeRequests()
.antMatchers("/").permitAll() //首页所有人可以访问
.antMatchers("/user/**").hasRole("LOGED")//user下的页面要LOGED角色才可以访问
.and()
.formLogin() //未授权跳转:以表单形式提交
.loginPage("/loginPage.html") //我们自己指定的登录页面
.permitAll()
.loginProcessingUrl("/login") //指定表单提交请求(这里我们用系统的,也可以用自己的登录逻辑,但是自己使用失败有Bug) 必须要跟html表单中的action一样
.permitAll() //登录地址本身也需要允许
// .defaultSuccessUrl("/index.html")//登陆成功后跳转地址
.usernameParameter("nickname") //自己设置登录账号和密码
.passwordParameter("pwd") //默认是username和password
.and()
.csrf().disable() //禁用csrf跨域。。。。不禁用的话post请求403
;
//无权限默认到登录页:用官网的的页面
// http.formLogin();
}
// @Bean
// public PasswordEncoder passwordEncoder(){
// // 使用BCrypt加密密码
// return new BCryptPasswordEncoder();
// }
//认证
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
//加密方案
BCryptPasswordEncoder encoder = new BCryptPasswordEncoder();
/* 1. 这里我们可以自己指定用户
auth
.inMemoryAuthentication()
.passwordEncoder(encoder)
.withUser("kk")
.password(encoder.encode("kk")).roles("loged");
*/
//认证规则里的用户从我们自定义的MyUserDetailService里读取,并用BCryptPasswordEncoder加密
// 2. 推荐使用我们自己指定的逻辑(用户、密码、角色权限)
auth.userDetailsService(myUserDetailService)
.passwordEncoder(encoder) //一定要加密
;
}
}
如何获取登录用户
//获取上下栈
SecurityContext context = SecurityContextHolder.getContext();
Authentication authentication1 = context.getAuthentication();
User principal = (User)authentication1.getPrincipal(); //这个就是我们在步骤2中写的User
后续可以将用户自己封装到session中
自定义User
我们如果不用系统的User,也可以自己指定,但是使用的时候出现了一些问题,最后还是决定用系统配的User
只需要将我们自己定义的User实现UserDetails
接口,重写方法即可