接上文SpringSecurity(一):https://mp.csdn.net/mp_blog/creation/editor/137512980
5、自定义处理器
-
自定义登录成功处理器
/**
* @Author 爱意随风(cdy)
* @Date 2024/4/7 17:08
* @Version 1.0
* @Describe 自定义登录成功处理器
*/
public class MyForwardAuthenticationSuccessHandler implements AuthenticationSuccessHandler {
private String url;
public MyForwardAuthenticationSuccessHandler(String url) {
this.url = url;
}
@Override
public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException {
response.sendRedirect(url);
}
}
-
自定义登录失败处理器
/**
* @Author 爱意随风(cdy)
* @Date 2024/4/7 17:10
* @Version 1.0
* @Describe 自定义登录失败处理器
*/
public class MyForwardAuthenticationFailureHandler implements AuthenticationFailureHandler {
private String url;
public MyForwardAuthenticationFailureHandler(String url) {
this.url = url;
}
@Override
public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response, AuthenticationException exception) throws IOException, ServletException {
response.sendRedirect(url);
}
}
-
SecurityConfig.java修改
//表单登录
http.formLogin()
.loginPage("/login.html")
.loginProcessingUrl("/login")
//必须是post请求,成功后跳转
//.successForwardUrl("/toMain")
//自定义登录成功处理器 需注释掉.successForwardUrl("/toMain")
.successHandler(new MyForwardAuthenticationSuccessHandler("/toMain"))
//必须是post请求,失败后跳转
//.failureForwardUrl("/toError")
//自定义登录成功处理器 需注释掉.failureForwardUrl("/toError")
.failureHandler(new MyForwardAuthenticationFailureHandler("/toError"));
6、anyRequest()
所有请求必须都认证才能访问,且有前后顺序,必须放在最后面。
//所有请求都必须通过认证才能访问
.anyRequest().authenticated();
7、antMatchers()
用于放行,匹配URL规则
-
?:匹配一个字符
-
*:匹配0个或多个字符
-
**:匹配0个或多个目录
实际项目需要放行所有静态资源以及js文件
.antMatchers("/js/**","/css/**").permitAll();
.antMatchers("/**/*.js").permitAll();
8、regexMatchers()
正则表达式
.regexMatchers("正则表达式").permitAll();
9、权限控制
修改main.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<titl>首页</titl></title>
</head>
<body>
<h1>登陆成功<a href="/main1.html">跳转</a></h1>
</body>
</html>
添加main1.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<titl>首页</titl></title>
</head>
<body>
<h1>权限控制</h1>
</body>
</html>
SecurityConfig.java添加
//权限控制 严格区分大小写 .antMatchers("/main1.html").hasAuthority("admin")
10、角色控制
修改UserDatailServiceImpl.java
//角色写到权限后面 角色名前必须加“ROLE_” ,例如ROLE_abc
return new User(username,encode, AuthorityUtils.commaSeparatedStringToAuthorityList("admin,ROLE_abc"));
SecurityConfig.java添加
//角色控制 严格区分大小写 不需要ROLE_开头 可以匹配多个
.antMatchers("/main1.html").hasAnyRole("abc")
11、IP控制
SecurityConfig.java添加
//基于IP控制
.antMatchers("/main1.html").hasIpAddress("127.0.0.1");
12、基于access访问控制
//基于access访问控制
.antMatchers("main.html").access("hasAnyRole('abc')");
13、自定义access方法
-
创建MyService接口
/**
* @Author 爱意随风(cdy)
* @Describe 自定义权限接口
* @Date 2024/4/8 11:45
*/
public interface MyService {
boolean hasPermission(HttpServletRequest request, Authentication authentication);
}
-
实现接口
/**
* @Author 爱意随风(cdy)
* @Describe
* @Date 2024/4/8 11:48
*/
@Service
public class MyServiceImpl implements MyService {
@Override
public boolean hasPermission(HttpServletRequest request, Authentication authentication) {
//获取主体
Object principal = authentication.getPrincipal();
//判断主体是否属于UserDetalis
if (principal instanceof UserDetails) {
//获取权限
UserDetails userDetails = (UserDetails) principal;
Collection<? extends GrantedAuthority> authorities = userDetails.getAuthorities();
//判断请求路径是否在权限里 request.getRequestURI()获取的是main.html权限
//前面加的main.html只是页面,权限里没有加new User(username,encode, AuthorityUtils.commaSeparatedStringToAuthorityList("admin,ROLE_abc,/main.html"));
System.out.println(request.getRequestURI());///main.html
return authorities.contains(new SimpleGrantedAuthority(request.getRequestURI()));
}
return false;
}
}
-
SecurityConfig.java修改
//自定义access方法 替换.anyRequest().authenticated();
.anyRequest().access("@myServiceImpl.hasPermission(request,authentication)");
14、基于注解控制
@Secured注解
-
需要在启动类用注解开启
@EnableGlobalMethodSecurity(securedEnabled = true)
-
关闭之前相应的控制,在对应方法加注解
@Secured("ROLE_abc")
@RequestMapping("/toMain")
@PreAuthorize/@PostAuthorize注解
-
@PreAuthorize表示访问方法或类在执行之前先判断权限,大多情况下都是使用这个注解,注解的参数和 access()方法参数取值相同,都是权限表达式。@PostAuthorize表示方法或类执行结束后判断权限,此注解很少被使用到。
-
开启注解
@EnableGlobalMethodSecurity(securedEnabled = true,prePostEnabled = true)
-
使用
// @Secured("ROLE_abc")角色控制
/*
* @Secured("ROLE_abc")
*/
/*
* @PreAuthorize("hasAnyRole('abc')")
* */
@RequestMapping("/toMain")
public String toMain(){
return "redirect:main.html";
}
15、退出登录
主页main添加退出
<a href="/logout">退出</a>
16、CSRF
-
CSRF(Cross Site Request Forgery,跨站请求伪造)。是一种对网站的恶意利用,通过伪装来自受信任用户的请求来利用受信任的网站。
-
原理是攻击者构造网站后台某个功能接口的请求地址,诱导用户去点击或者用特殊方法让该请求地址自动加载。用户在登录状态下这个请求被服务端接收后会被误以为是用户合法的操作。对于 GET 形式的接口地址可轻易被攻击,对于 POST 形式的接口地址也不是百分百安全,攻击者可诱导用户进入带 Form 表单可用POST方式提交参数的页面。
-
目前防御 CSRF 攻击主要有三种策略:
-
验证 HTTP Referer 字段;
-
在请求地址中添加 token 并验证;
-
在 HTTP 头中自定义属性并验证。
-
END
获取更多精彩后续请关注博主。。。