Spring Security
启用Spring Security
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
配置Spring Security
/**
* @author qingtian
* @date 2021-02-07 10:24
*/
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
}
储存用户信息
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
// //基于内存的用户存储
//
// @Override
// protected void configure(AuthenticationManagerBuilder auth) throws Exception {
//
// auth.inMemoryAuthentication()
// .withUser("buzz")
// .password("infinity")
// .authorities("ROLE_USER")
// .and()
// .withUser("woody")
// .password("bullseye")
// .authorities("ROLE_USER");
// }
// //基于jdbc的用户储存
// @Autowired
// private DataSource dataSource;
//
//
// @Override
// protected void configure(AuthenticationManagerBuilder auth) throws Exception {
//
// auth.jdbcAuthentication()
// .dataSource(dataSource)
// .usersByUsernameQuery(
// "select username,password,enabled from Users"+"where username=?"
// )
// .authoritiesByUsernameQuery(
// "select username, authority from UserAuthorities"+"where username=?"
// )
// //使用转码后的密码
// .passwordEncoder(new BCryptPasswordEncoder());
// }
//以LDAP作为后端的用户储存
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
// auth.ldapAuthentication()
// .userSearchFilter("(uid={0})")//搜索用户
// .groupSearchFilter("member = {0}");//搜索组
//在默认情况下用户和组的搜索都是空的,就是表明从LDAP的根目录开始搜索
//可以更改
auth.ldapAuthentication()
.userSearchBase("ou = people")//为用户查询提供了基础查询
.userSearchFilter("(uid = {0})")
.groupSearchBase("ou = groups")//查找组提供了基础查询,在groups下查询
.groupSearchFilter("member = {0}")
//设置密码比对
.passwordCompare()
.passwordEncoder(new BCryptPasswordEncoder())
//设置密码属性的名称
.passwordAttribute("passcode");
//默认情况下Spring假设LDAP服务器监听本机的33389端口,如果LDAP服务器在另一台机器上,可以通过contextSource()方法配置地址
}
}
保护web请求
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
private UserDetailsService userDetailsService;
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userDetailsService);
}
@Override
protected void configure(HttpSecurity http) throws Exception {
//具备ROLE_USER权限的用户才能访问"/design"和"/orders"
//其他请求允许所有用户访问
http.authorizeRequests()
.antMatchers("/design","/orders")
.hasRole("ROLE_USER")
.antMatchers("/","/**").permitAll();
}
}
用来定义如何保护路径的配置方法
Spring Security对Spring表达式语言的扩展
重写以上的表达式规则
我们只允许具备ROLE_USER权限的用户在星期二创建新taco
@Override
protected void configure(HttpSecurity http) throws Exception {
// http.authorizeRequests()
// .antMatchers("/design","/orders")
// .hasRole("ROLE_USER")
// .antMatchers("/","/**").permitAll();
http.authorizeRequests()
.antMatchers("/design","/orders")
.access("hasRole('ROLE_USER')&&"+"T(java.util.Calendar).getInstance().get("+"T(java.util.Calendar).DAY_OF_WEEK) == "+"T(java.util.Calendar).THURSDAY")
.antMatchers("/","/**").access("permitAll()");
}
创建自定义的登录页
@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.antMatchers("/design","/orders")
.hasRole("ROLE_USER")
.antMatchers("/","/**").permitAll()
.and()
.formLogin()
.loginPage("/login");
@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.antMatchers("/design","/orders")
.hasRole("ROLE_USER")
.antMatchers("/","/**").permitAll()
.and()
.formLogin()
//登录
.loginPage("/login")
.loginProcessingUrl("/authenticate")
.usernameParameter("user")
.passwordParameter("pwd")
//退出
.defaultSuccessUrl("/design",true)
.and()
.logout()
.logoutSuccessUrl("/")
.and()
.csrf().disable();
了解当前的用户
/**
* @author qingtian
* @date 2021-02-08 10:05
*/
@Controller
public class OrderControlller {
@Autowired
private UserRepository userRepository;
//了解用户是谁
/**
* 注入Principal对象到控制器方法中
* @param order
* @param errors
* @param sessionStatus
* @param principal
* @return
*/
@PostMapping
public String ProcessOrder(Order order, Errors errors, SessionStatus sessionStatus, Principal principal) {
User user = userRepository.findByUsername(principal.getName());
order.setUser(user);
return "ok";
}
/**
* 注入Authentication对象到控制器方法中
* @param order
* @param errors
* @param sessionStatus
* @param authentication
* @return
*/
@PostMapping
public String ProcessOrder(Order order, Errors errors, SessionStatus sessionStatus, Authentication authentication) {
User user = (User) authentication.getPrincipal();
order.setUser(user);
return "ok";
}
@PostMapping
public String ProcessOrder(Order order, Errors errors, SessionStatus sessionStatus, @AuthenticationPrincipal User user) {
//使用@AuthenticationPrincipal的好处是不需要类型转换
order.setUser(user);
return "ok";
}
/**
* 还有另外一种方法能够识别当前的认证用户是谁,但是这种方法有点麻烦,他会包含大量安全性相关的代码。我们
* 可以从安全上下文中获取一个Authentication对象
*/
@PostMapping
public String ProcessOrder(Order order, Errors errors, SessionStatus sessionStatus) {
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
User principal = (User) authentication.getPrincipal();
order.setUser(principal);
return "ok";
}
评论区