【Spring-Security】Re05 权限控制及403处理
一、访问控制方法及控制项:
上述配置中的URL后面都离不开的一个访问控制抉择:

1、全部允许 PermiAll
2、全部拒绝 DenyAll
3、允许匿名访问 Anonymous 也就是普通访问者
4、允许认证之后访问 Authenticated
5、必须完全认证? FullAuthenticated
6、记住我 RememberMe
二、Security权限控制对资源的访问:
之前的权限配置中我们有设置一个权限的角色属性:
package cn.zeal4j.service; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.authority.AuthorityUtils;
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.core.userdetails.UsernameNotFoundException;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service; /**
* @author Administrator
* @file IntelliJ IDEA Spring-Security-Tutorial
* @create 2020 09 27 21:57
*/
@Service
public class UserDetailsServiceImpl implements UserDetailsService { @Autowired
private PasswordEncoder passwordEncoder; @Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException { // 1、通过提供的用户名参数访问数据库,查询记录返回过来,如果记录不存在则抛出异常
// username = "admin";
if (!"admin".equals(username)) throw new UsernameNotFoundException("用户名不存在"); // 2、查询出来的凭证是被加密了的,这里是模拟查询的密码
String encode = passwordEncoder.encode("123456"); // 权限不可以为空,所以需要这么一个工具方法简单实现
return new User(username, encode, AuthorityUtils.commaSeparatedStringToAuthorityList("admin,normal"));
}
}
现在我们设置两个特定的资源页面:

页面的内容区别就是这个:
<h3>Only admin Allowed</h3>
<h3>Only vip-01 Allowed</h3>
控制器处理:
package cn.zeal4j.controller; import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping; /**
* @author Administrator
* @file Spring-Security-Tutorial
* @create 2020 09 28 13:59
*/
@Controller
public class PermitController { @RequestMapping("admin.page")
public String toAdminPage() {
return "permit/admin";
} @RequestMapping("vip-01.page")
public String toVip01Page() {
return "permit/vip-01";
}
}
现在设置访问权限:
通过hasAuthority方法进行鉴权,具备资质才会允许访问
package cn.zeal4j.configuration; import cn.zeal4j.handler.FarsAuthenticationFailureHandler;
import cn.zeal4j.handler.FarsAuthenticationSuccessHandler;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpMethod;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder; /**
* @author Administrator
* @file IntelliJ IDEA Spring-Security-Tutorial
* @create 2020 09 27 21:55
*/
@Configuration
public class SecurityConfiguration extends WebSecurityConfigurerAdapter { @Bean
public PasswordEncoder getPasswordEncoder() {
return new BCryptPasswordEncoder();
} @Override
protected void configure(HttpSecurity httpSecurity) throws Exception {
httpSecurity.formLogin(). // 设置登陆行为方式为表单登陆
// 登陆请求参数设置
usernameParameter("username").
passwordParameter("password").
loginPage("/login.html"). // 设置登陆页面URL路径
loginProcessingUrl("/login.action"). // 设置表单提交URL路径
// successForwardUrl("/main.page"). // 设置认证成功跳转URL路径 POST请求
successHandler(new FarsAuthenticationSuccessHandler("https://www.acfun.cn/")). // 使用自定义的重定向登陆
// failureForwardUrl("/error.page"); // 设置认证失败跳转URL路径 POST请求
failureHandler(new FarsAuthenticationFailureHandler("/error.html")); // 跨域处理,不需要跳转了 httpSecurity.authorizeRequests().
regexMatchers(HttpMethod.POST, "正则表达式").permitAll(). // 还可以对符合正则表达式的请求方式进行要求,这个属性使用来制定请求的方式
antMatchers("/**/*.js", "/**/*.css", "/**/images/*.*").permitAll(). // 静态资源放行
antMatchers("/login.html").permitAll(). // 登陆页面允许任意访问
antMatchers("/error.html").permitAll(). // 失败跳转后重定向的页面也需要被允许访问
antMatchers("/admin.page").hasAnyAuthority("admin").
antMatchers("/vip-01.page").hasAnyAuthority("vip-01").
// mvcMatchers("/main.page").servletPath("/xxx").permitAll(). // mvcMatchers资源放行匹配
// antMatchers("/xxx/main.page").permitAll(). // 或者多写MSP的前缀
anyRequest().authenticated(); // 其他请求均需要被授权访问 // CSRF攻击拦截关闭
httpSecurity.csrf().disable();
}
}
访问测试:
我们默认登录之后赋予的权限中包含admin,所以访问admin.page是没有问题的

但是如果访问vip-01.page,则会报403错误,访问被禁止了

三、角色控制:
上述的权限设置中可以同时设置角色,书写规范是:
ROLE_角色名称
例如这样:
package cn.zeal4j.service; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.authority.AuthorityUtils;
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.core.userdetails.UsernameNotFoundException;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service; /**
* @author Administrator
* @file IntelliJ IDEA Spring-Security-Tutorial
* @create 2020 09 27 21:57
*/
@Service
public class UserDetailsServiceImpl implements UserDetailsService { @Autowired
private PasswordEncoder passwordEncoder; @Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException { // 1、通过提供的用户名参数访问数据库,查询记录返回过来,如果记录不存在则抛出异常
// username = "admin";
if (!"admin".equals(username)) throw new UsernameNotFoundException("用户名不存在"); // 2、查询出来的凭证是被加密了的,这里是模拟查询的密码
String encode = passwordEncoder.encode("123456"); // 权限不可以为空,所以需要这么一个工具方法简单实现
return new User(username, encode, AuthorityUtils.commaSeparatedStringToAuthorityList("admin,normal,ROLE_vip-01"));
}
}
之前访问不了的VIP-01资源,现在权限控制规则可以这样设置:
package cn.zeal4j.configuration; import cn.zeal4j.handler.FarsAuthenticationFailureHandler;
import cn.zeal4j.handler.FarsAuthenticationSuccessHandler;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpMethod;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder; /**
* @author Administrator
* @file IntelliJ IDEA Spring-Security-Tutorial
* @create 2020 09 27 21:55
*/
@Configuration
public class SecurityConfiguration extends WebSecurityConfigurerAdapter { @Bean
public PasswordEncoder getPasswordEncoder() {
return new BCryptPasswordEncoder();
} @Override
protected void configure(HttpSecurity httpSecurity) throws Exception {
httpSecurity.formLogin(). // 设置登陆行为方式为表单登陆
// 登陆请求参数设置
usernameParameter("username").
passwordParameter("password").
loginPage("/login.html"). // 设置登陆页面URL路径
loginProcessingUrl("/login.action"). // 设置表单提交URL路径
// successForwardUrl("/main.page"). // 设置认证成功跳转URL路径 POST请求
successHandler(new FarsAuthenticationSuccessHandler("https://www.acfun.cn/")). // 使用自定义的重定向登陆
// failureForwardUrl("/error.page"); // 设置认证失败跳转URL路径 POST请求
failureHandler(new FarsAuthenticationFailureHandler("/error.html")); // 跨域处理,不需要跳转了 httpSecurity.authorizeRequests().
regexMatchers(HttpMethod.POST, "正则表达式").permitAll(). // 还可以对符合正则表达式的请求方式进行要求,这个属性使用来制定请求的方式
antMatchers("/**/*.js", "/**/*.css", "/**/images/*.*").permitAll(). // 静态资源放行
antMatchers("/login.html").permitAll(). // 登陆页面允许任意访问
antMatchers("/error.html").permitAll(). // 失败跳转后重定向的页面也需要被允许访问
antMatchers("/admin.page").hasAnyAuthority("admin").
/*antMatchers("/vip-01.page").hasAnyAuthority("vip-01").*/
antMatchers("/vip-01.page").hasRole("vip-01").
// mvcMatchers("/main.page").servletPath("/xxx").permitAll(). // mvcMatchers资源放行匹配
// antMatchers("/xxx/main.page").permitAll(). // 或者多写MSP的前缀
anyRequest().authenticated(); // 其他请求均需要被授权访问 // CSRF攻击拦截关闭
httpSecurity.csrf().disable();
}
}
重启项目运行:
现在VIP-01资源可以被正常的访问了:

案例演示只是使用了单一的角色和权限处理,但实际开发的环境下面更为复杂,Security对此也提供好了 多权限 + 多角色的API

四、IP地址判断:
在之前的JavaWeb的学习中,我们可以通过请求的HttpServletRequest对象中,获取发送的请求的客户端IP地址

注意在本机上的一些访问问题:
以不同的IP地址形式访问,服务端接受到的IP地址也是不一样的
1、第一种
http://localhost:8080/
打印结果 0:0:0:0:0:0:0:1 2、第二种
http://127.0.0.1:8080/
打印结果 127.0.0.1 3、第三种
http://192.168.43.180:8080/
打印结果 192.168.43.180
这里新建一个资源,仅限于第三种IP地址符合的控制
<h3>Only 192.168.43.180 IP-Host Allowed</h3>
然后配置控制器和权限:
@RequestMapping("ip.page")
public String toIpPage() {
return "permit/ip";
}
看看非远程IP地址是否有效
antMatchers("/ip.page").hasIpAddress("192.168.43.180").
可以看到,使用Localhost是不被允许访问的

同样的127.0.0.1地址也不允许

只有最后的远程IP地址才能被允许访问:

五、自定义403处理方案
除了这样的403响应,前后端分离的处理是发送响应状态信息完成的,所以Security允许我们自己设置一个禁止访问的结果的处理
package cn.zeal4j.handler; import org.springframework.security.access.AccessDeniedException;
import org.springframework.security.web.access.AccessDeniedHandler; import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter; /**
* @author Administrator
* @file Spring-Security-Tutorial
* @create 2020 09 28 14:37
*/
@Component
public class CustomAccessDeniedHandler implements AccessDeniedHandler { @Override
public void handle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, AccessDeniedException e) throws IOException, ServletException {
httpServletResponse.setStatus(HttpServletResponse.SC_FORBIDDEN);
httpServletResponse.setHeader("Content-Type", "application/json;charset=utf-8"); PrintWriter printWriter = httpServletResponse.getWriter();
// json数据 : { "status" : "error" , "message" : "权限不足,访问被禁止!!!" }
printWriter.print("{ \"status\" : \"error\" , \"message\" : \"权限不足,访问被禁止!!!\" }");
printWriter.flush();
printWriter.close();
}
}
然后在配置类中设置,403访问禁止的异常抛出:
package cn.zeal4j.configuration; import cn.zeal4j.handler.CustomAccessDeniedHandler;
import cn.zeal4j.handler.FarsAuthenticationFailureHandler;
import cn.zeal4j.handler.FarsAuthenticationSuccessHandler;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpMethod;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.access.AccessDeniedHandler; /**
* @author Administrator
* @file IntelliJ IDEA Spring-Security-Tutorial
* @create 2020 09 27 21:55
*/
@Configuration
public class SecurityConfiguration extends WebSecurityConfigurerAdapter { @Autowired
private AccessDeniedHandler accessDeniedHandler; @Bean
public PasswordEncoder getPasswordEncoder() {
return new BCryptPasswordEncoder();
} @Override
protected void configure(HttpSecurity httpSecurity) throws Exception {
httpSecurity.formLogin(). // 设置登陆行为方式为表单登陆
// 登陆请求参数设置
usernameParameter("username").
passwordParameter("password").
loginPage("/login.html"). // 设置登陆页面URL路径
loginProcessingUrl("/login.action"). // 设置表单提交URL路径
// successForwardUrl("/main.page"). // 设置认证成功跳转URL路径 POST请求
successHandler(new FarsAuthenticationSuccessHandler("https://www.acfun.cn/")). // 使用自定义的重定向登陆
// failureForwardUrl("/error.page"); // 设置认证失败跳转URL路径 POST请求
failureHandler(new FarsAuthenticationFailureHandler("/error.html")); // 跨域处理,不需要跳转了 httpSecurity.authorizeRequests().
regexMatchers(HttpMethod.POST, "正则表达式").permitAll(). // 还可以对符合正则表达式的请求方式进行要求,这个属性使用来制定请求的方式
antMatchers("/**/*.js", "/**/*.css", "/**/images/*.*").permitAll(). // 静态资源放行
antMatchers("/login.html").permitAll(). // 登陆页面允许任意访问
antMatchers("/error.html").permitAll(). // 失败跳转后重定向的页面也需要被允许访问
antMatchers("/admin.page").hasAnyAuthority("admin").
/*antMatchers("/vip-01.page").hasAnyAuthority("vip-01").*/
antMatchers("/vip-01.page").hasRole("vip-01").
antMatchers("/ip.page").hasIpAddress("192.168.43.180").
// mvcMatchers("/main.page").servletPath("/xxx").permitAll(). // mvcMatchers资源放行匹配
// antMatchers("/xxx/main.page").permitAll(). // 或者多写MSP的前缀
anyRequest().authenticated(); // 其他请求均需要被授权访问 // CSRF攻击拦截关闭
httpSecurity.csrf().disable(); httpSecurity.exceptionHandling().accessDeniedHandler(accessDeniedHandler); }
}
403访问测试:

【Spring-Security】Re05 权限控制及403处理的更多相关文章
- request.getRemoteUser() Spring Security做权限控制后
一. request.getRemoteUser();//获取当前缓存的用户,比如Spring Security做权限控制后就会将用户登录名缓存到这里 request.getRemoteAddr(); ...
- 在Spring Boot中使用Spring Security实现权限控制
丢代码地址 https://gitee.com/a247292980/spring-security 再丢pom.xml <properties> <project.build.so ...
- spring boot+freemarker+spring security标签权限判断
spring boot+freemarker+spring security标签权限判断 SpringBoot+SpringSecurity+Freemarker项目中在页面上使用security标签 ...
- Spring Boot中使用 Spring Security 构建权限系统
Spring Security是一个能够为基于Spring的企业应用系统提供声明式的安全访问控制解决方案的安全框架.它提供了一组可以在Spring应用上下文中配置的Bean,为应用系统提供声明式的安全 ...
- 单点登录系统使用Spring Security的权限功能
背景 在配置中心增加权限功能 目前配置中心已经包含了单点登录功能,可以通过统一页面进行登录,登录完会将用户写入用户表 RBAC的用户.角色.权限表CRUD.授权等都已经完成 希望不用用户再次登录,就可 ...
- 使用Spring Security实现权限管理
使用Spring Security实现权限管理 1.技术目标 了解并创建Security框架所需数据表 为项目添加Spring Security框架 掌握Security框架配置 应用Security ...
- Spring Boot整合实战Spring Security JWT权限鉴权系统
目前流行的前后端分离让Java程序员可以更加专注的做好后台业务逻辑的功能实现,提供如返回Json格式的数据接口就可以.像以前做项目的安全认证基于 session 的登录拦截,属于后端全栈式的开发的模式 ...
- SpringBoot + Security实现权限控制
网上找了好几个,因为各种原因不太行,下面这个亲测可行 参考:https://blog.csdn.net/u012702547/article/details/54319508 基于SpringBoot ...
- springBoot整合spring security实现权限管理(单体应用版)--筑基初期
写在前面 在前面的学习当中,我们对spring security有了一个小小的认识,接下来我们整合目前的主流框架springBoot,实现权限的管理. 在这之前,假定你已经了解了基于资源的权限管理模型 ...
- Spring Boot 集成 Spring Security 实现权限认证模块
作者:王帅@CodeSheep 写在前面 关于 Spring Security Web系统的认证和权限模块也算是一个系统的基础设施了,几乎任何的互联网服务都会涉及到这方面的要求.在Java EE领 ...
随机推荐
- docker on windows v19 红色启动不了
遇到: error during connect: Get http://%2F%2F.%2Fpipe%2Fdocker_engine/v1.40/containers/json: open //./ ...
- ESP8266串口WiFi模块 - WiFi杀手
Tips:当你看到这个提示的时候,说明当前的文章是由原emlog博客系统搬迁至此的,文章发布时间已过于久远,编排和内容不一定完整,还请谅解` ESP8266串口WiFi模块 - WiFi杀手 日期:2 ...
- 洛谷 P1226 快速幂
题目链接:快速幂 思路 简单快速幂模板.a ^ 17 = (a ^ 2) ^ 8 * a,此时pow()中的y就可以视为17 -> 8(y >>= 1),pow()中的x就是底数a ...
- Kubernetes 审计(Auditing)
目录 一.系统环境 二.前言 三.Kubernetes 审计简介 四.审计策略简介 五.启用审计 5.1 引入审计 5.2 启用审计 六.审计策略 6.1 记录审计阶段为:ResponseStarte ...
- 我对《RAG/大模型/非结构化数据知识库类产品》技术架构的思考、杂谈
1.前言 在6.28/29的稀土掘金开发者大会RAG专场上,我们公司CEO员外代表TorchV分享了我们在<RAG在企业应用中落地的难点与创新> 其中最后分享了两个观点: AI在应用场景落 ...
- 详解Web应用安全系列(7)使用具有已知漏洞的组件
使用具有已知漏洞的组件,这种安全漏洞普遍存在,基于组件开发的模式使得多数开发团队根本不了解其应用或API中使用的组件,更谈不上及时更新这些组件了. 下面就分别以.NET和Java各分享一个案例. .N ...
- Python2 SyntaxError: Non-ASCII character '\xc3' in file...
使用pip安装完需要的python库,运行脚本时报错:Syntax Error: Non-ASCII character '\xc3' in file /usr/local/lib/python2.7 ...
- SSM配置文件分类及总结
配置组件通常涉及以下几个方面 数据访问配置 配置数据源.JdbcTemplate.事务管理器等,以支持数据库操作. 服务层与DAO层配置 定义服务类和服务实现类.数据访问对象(DAO)的bean,以及 ...
- yb课堂之自定义异常和配置 《五》
开发自定义异常和配置 自定义异常 继承RuntimeException 开发异常处理器ExceptionHandle YBException.java package net.ybclass.onli ...
- win10打不出中文的修复方法!
说明 在Win10系统中,默认自带了中文输入法,使用起来非常的方便,但有时win10系统中自带的输入法会打不出中文的情况,该怎么办呢?遇到这样的问题,我们可以参考下本文中的方法来修复. 步骤: cmd ...