拦截相应没有访问权限访问页面的用户,注意authorizeRequests与authorizeHttpRequests不能混用,不然报错。
import jakarta.annotation.Resource;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.method.configuration.EnableMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.web.SecurityFilterChain;
@Configuration
@EnableWebSecurity
@EnableMethodSecurity(prePostEnabled = true)
public class MyWebSecurityConfig {
@Resource
private UserDetailsService userDetailsService;
@Bean
SecurityFilterChain securityFilterChain(HttpSecurity httpSecurity) throws Exception {
//配置web授权访问,"/login","/register","/upLogin"这些统统无需权限
httpSecurity.authorizeHttpRequests().requestMatchers("/login","register","/upLogin").permitAll()
//成功的链接,也就是后续访问的链接放在这个里,我这里是成功页需要USER权限才能访问
.requestMatchers("/success").hasAnyRole("USER").and()
/**
* 自定义登陆页面是loginSelf.html页(这里看你模板引擎怎么配),表单提交的处理链接是"/upLogin"
* 就是<form action="/upLogin"></form>这样,这个"/upLogin"不需要自己处理,就自己决定
* usernameParameter和passwordParameter,就是表单提交所带的参数,
* 这里我是"username"和"password";
*/
.formLogin().loginPage("/loginSelf").loginProcessingUrl("upLogin")
.usernameParameter("username").passwordParameter("password");
return httpSecurity.build();
}
}
以下为新版本
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
@Configuration
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
// http.authorizeRequests() //授权请求
// .anyRequest()//任何请求
// .denyAll();//拒绝
http.authorizeRequests()
//.regexMatchers("/student/**") //这种匹配方式可以不用学
//.antMatchers("/student/**") //这种匹配方式可以不用学
.mvcMatchers("/student/**") //匹配这个url
//.hasRole("") //是否有单个角色
//.hasAnyRole("") //是否有任意角色
//.access("hasAuthority('student:query') or hasRole('admin')") //另外一种权限设置
.hasAnyAuthority("student:add") //拥有这个权限的用户可以访问这个/student/** ,是否其中至少一个权限
.mvcMatchers("/teacher/**") //匹配url
.hasAuthority("ROLE_teacher") //拥有这个权限的用户可以访问/teacher/**
.anyRequest() //任何请求
.authenticated(); //都需要登录 ,注意,没有配置mvc的只要登录成功就可以访问
http.formLogin().permitAll(); //允许表单登录
}
}
匹配路径url的写法有三种,判断权限有五种。
基于方法粒度的权限校验一定要记得在Security配置类中加上@EnableGlobalMethodSecurity注解设置prePostEnabled=true参数,否则直接使用注解配置权限将会无效!!!
import org.springframework.context.annotation.Bean;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
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.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.provisioning.InMemoryUserDetailsManager;
//@Configuration 这里不需要加Configuration是因为下面这个注解已经带有Config注解了
@EnableGlobalMethodSecurity(prePostEnabled = true) //开启全局方法安全
public class SecurityUserConfig {
@Bean
public UserDetailsService userDetailsService(){
UserDetails u1 = User.builder()
.username("cbq1")
.password(passwordEncoder().encode("123456"))
.roles("student")
.build();
UserDetails u2 = User.builder()
.username("cbq2")
.password(passwordEncoder().encode("123456"))
.authorities("teacher:update","teacher:query")
.build();
InMemoryUserDetailsManager inMemoryUserDetailsManager = new InMemoryUserDetailsManager();
inMemoryUserDetailsManager.createUser(u1);
inMemoryUserDetailsManager.createUser(u2);
return inMemoryUserDetailsManager;
}
@Bean
public PasswordEncoder passwordEncoder(){
return new BCryptPasswordEncoder();
}
}
配置完之后即可使用了:
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("teacher")
public class TeacherController {
@GetMapping("add")
@PreAuthorize("hasRole('teacher')") //预授权
public Object add(){
return "添加成功";
}
@GetMapping("delete")
@PreAuthorize("hasRole('teacher')")
public Object delete(){
return "删除成功";
}
@GetMapping("update")
@PreAuthorize("hasRole('teacher') or hasAuthority('teacher:update')")
public Object update(){
return "更新成功";
}
}
设置登录成功返回json创建一个类并且实现AuthenticationSuccessHandler接口,
import com.example.springsecuritystudy3.vo.HttpResult;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.security.core.Authentication;
import org.springframework.security.web.authentication.AuthenticationSuccessHandler;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
/**
* @description: 只要认证成功那么久返回json
* @author 长白崎
* @date 2023/7/17 5:11
* @version 1.0
*/
@Slf4j
@Component
public class AppAuthenticationSuccessHandler implements AuthenticationSuccessHandler {
@Resource
private ObjectMapper objectMapper;
@Override
public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException {
HttpResult httpResult = HttpResult.builder()
.code(1)
.msg("登录成功")
.build();
String responseJson = objectMapper.writeValueAsString(httpResult);
response.setCharacterEncoding("UTF-8");
response.setContentType("application/json;charset=utf-8");
PrintWriter writer = response.getWriter();
writer.println(responseJson);
writer.flush();
}
}
实现接口之后只需要Security配置类当中配置好即可。
import lombok.extern.slf4j.Slf4j;
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 javax.annotation.Resource;
@Configuration
@Slf4j
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
@Resource
AppAuthenticationSuccessHandler appAuthenticationSuccessHandler;
@Resource
AppAuthenticationFailureHandler appAuthenticationFailureHandler;
@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.anyRequest()
.authenticated();
//设置登录成功处理器
http.formLogin()
.successHandler(appAuthenticationSuccessHandler) //配置登录成功事件
.failureHandler(appAuthenticationFailureHandler) //配置登录失败事件
.permitAll();
}
}