热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

SpringSecurity集成与使用

说明security会对服务端的接口添加权限过滤,不具备权限的请求将被拒绝。引入security要引入security,只需添加依赖即可ÿ

说明

security会对服务端的接口添加权限过滤,不具备权限的请求将被拒绝。


引入security

要引入security,只需添加依赖即可:
在pom.xml中引入security:

<dependency><groupId>org.springframework.bootgroupId><artifactId>spring-boot-starter-securityartifactId>
dependency>

运行工程&#xff0c;控制台会生成一个随机的密码&#xff1a;
generatePassword

当用浏览器访问服务端接口时&#xff0c;会提示输入用户名和密码。用户名为user&#xff0c;密码即为生成的随机密码。该验证方式为httpSecurity basic验证。
若要直接调用接口访问&#xff0c;则需要在请求头的Authorization中附加用户名/密码。
postman

使用postman时&#xff0c;需要将请求的Authorization属性的TYPE设置为Basic Auth

若要关闭该验证功能&#xff0c;则为Application启动类的&#64;SpringBootApplication注解添加排除类SecurityAutoConfiguration.class&#xff1a;

&#64;SpringBootApplication(exclude&#61;SecurityAutoConfiguration.class)
public class DemoApplication {public static void main(String[] args) {SpringApplication.run(DemoApplication.class, args);}
}

但该方式的优先级低于配置类。若配置类设置了开启验证&#xff0c;则依然还是需要进行验证。


设置


设置用户名和密码

在application.properties中添加属性&#xff1a;

spring.security.user.name&#61;user
spring.security.user.password&#61;123

这样&#xff0c;就将security验证的用户名和密码修改为user123但这样意味着登录系统的用户名和密码是固定的&#xff0c;不推荐。
若使用配置类&#xff0c;则可以不用在application.properties中添加属性&#xff0c;而是直接在配置类中设置。
配置类优先级更高。若配置类中没有设置用户名和密码&#xff0c;则使用application.properties中的设置。


使用配置类

添加一个配置类&#xff1a;

&#64;EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {// 设置密码验证方式&#64;Beanpublic PasswordEncoder passwordEncoder() {return new BCryptPasswordEncoder();}// 设置对各个接口的访问过滤&#64;Overrideprotected void configure(HttpSecurity httpSecurity) throws Exception {httpSecurity.authorizeRequests() // 对请求进行授权.antMatchers("/login","/version").permitAll() // 设置不需要认证的请求.antMatchers("/test").hasAuthority("p1") // 设置/test接口需要p1权限.anyRequest().authenticated() // 设置所有请求都需要认证.and() // 上一项配置已经结束&#xff0c;下一项配置将开始.httpBasic(); // 开启httpBasic登录httpSecurity.csrf().disable(); // 关闭默认csrf认证}// 设置对静态资源的访问过滤&#64;Overridepublic void configure(WebSecurity web) throws Exception {// 设置不拦截的静态资源web.ignoring().antMatchers("/file/**","/images/**");}
}

其中:


  • &#64;EnableWebSecurity:开启Security功能&#xff0c;从而支持Security的注解。
  • 若密码不需要使用任何加密&#xff0c;则passwordEncoder()的返回可设置为NoOpPasswordEncoder.getInstance()
  • antMatchers():可传入多个String参数&#xff0c;用于匹配多个请求API。结合permitAll()&#xff0c;可同时对多个请求设置忽略认证。
  • and():用于表示上一项配置已经结束&#xff0c;下一项配置将开始。

然后创建一个Service文件用于Security查询用户信息&#xff1a;

&#64;Service
public class SpringDataUserDetailsService implements UserDetailsService {&#64;AutowiredUserDao userDao;// 根据账号查询用户信息&#64;Overridepublic UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {UserDto userDto &#61; userDao.getUserByUsername(username);if(userDto &#61;&#61; null){// 如果用户查不到&#xff0c;返回null&#xff0c;由provider来抛出异常return null;}// 根据用户的id查询用户的权限List<String> permissions &#61; userDao.findPermissionsByUserId(userDto.getId());//将permissions转成数组String[] permissionArray &#61; new String[permissions.size()];permissions.toArray(permissionArray);UserDetails userDetails &#61; User.withUsername(userDto.getUsername()).password(userDto.getPassword()).authorities(permissionArray).build();return userDetails;}
}

当用户请求时&#xff0c;Security便会拦截请求&#xff0c;取出其中的username字段&#xff0c;从Service中查询该账户&#xff0c;并将信息填充到一个userDetails对象中返回。这样Security便拿到了填充后的userDetails对象&#xff0c;也就是获取到了包括权限在内的用户信息。


验证

Security默认开启session。
配置好之后&#xff0c;当用户请求时&#xff0c;会要求先进行登录。若登陆成功&#xff0c;就会返回给用户一个session。
之后当用户访问接口时&#xff0c;每次都会对请求进行拦截过滤&#xff0c;取出session进行查询判断&#xff0c;验证是否具有接口的访问权限。
若有权限&#xff0c;则返回正常结果&#xff1b;否则返回403错误。


退出登录

由于使用session&#xff0c;因此退出登录需要将请求中的session清除&#xff1a;

&#64;RequestMapping("/logout")
public String logout(HttpSession session){session.invalidate();return "退出成功";
}

然后设置httpSecurity.logout().logoutUrl("/logout")&#xff0c;注意logoutUrl需要设置为自定义的接口。


WebSecurityConfigurerAdapter.configure(HttpSecurity httpSecurity)相关

配置文件中&#xff0c;configure(HttpSecurity httpSecurity)用于定义一系列的过滤规则。


顺序优先级

整个http.xxx的校验是按照配置的顺序从上往下进行。若某个条件已匹配过&#xff0c;则后续同条件的匹配将不再被执行。也就是说&#xff0c;若多条规则是相互矛盾的&#xff0c;则只有第一条规则生效。典型地&#xff1a;

// 只有具有权限a的用户才能访问/get/resource
httpSecurity.authorizeRequests().antMatchers("/get/resource").hasAuthority("a").anyRequest().permitAll();// 所有用户都能访问/get/resource
httpSecurity.authorizeRequests().anyRequest().permitAll().antMatchers("/get/resource").hasAuthority("a");

但若是包含关系&#xff0c;则需要将细粒度的规则放在前面&#xff1a;

// /get/resource需要权限a&#xff0c;除此之外所有的/get/**都可以随意访问
httpSecurity.authorizeRequests().antMatchers("/get/resource").hasAuthority("a").antMatchers("/get/**").permitAll();

授权方式

授权有两种方式&#xff1a;


  • web授权&#xff08;基于请求url&#xff09;&#xff0c;在configure(HttpSecurity httpSecurity)中设置。
  • 方法授权&#xff08;在方法上使用注解标明授权&#xff09;。

web授权

&#64;Override
httpSecurity.authorizeRequests() // 对请求进行授权.antMatchers("/test1").hasAuthority("p1") // 设置/test1接口需要p1权限.antMatchers("/test2").hasAnyRole("admin", "manager") // 设置/test2接口需要admin或manager角色.and() // 上一项配置已经结束&#xff0c;下一项配置将开始.httpBasic(); // 开启httpBasic登录

其中&#xff1a;


  • hasAuthority("p1")表示需要p1权限
  • hasAnyAuthority("p1", "p2")表示p1或p2权限皆可

同理&#xff1a;


  • hasRole("p1")表示需要p1权限
  • hasAnyRole("p1", "p2")表示p1或p2权限皆可

方法授权

&#64;PreAuthorize("hasAuthority(&#39;p&#39;)")// 拥有p权限才可以访问
public String getResource(){return "访问资源";
}

在其中可以使用表达式&#xff1a;

&#64;PreAuthorize("#user.name.equals(&#39;admin&#39;)")
public void getResource(User user) {System.out.println("只有管理员才能获取到的数据");
}

也可以基于角色&#xff1a;

&#64;PreAuthorize("hasAnyRole(&#39;admin&#39;, &#39;manager&#39;)")
public void getResource(User user) {System.out.println("只有管理者才能获取到的数据");
}

表单登录

访问接口时&#xff0c;默认会打开一个登录页面&#xff0c;这就是表单登录。

httpSecurity.authorizeRequests().and().formLogin()//允许表单登录.successForwardUrl("/login-success");//自定义登录成功的页面地址

其中formLogin()表示允许表单登录。当调用了该方法&#xff0c;即会显示登录页面。
表单登录默认开启。若重载configure(HttpSecurity httpSecurity)且在其中没有调用formLogin()&#xff0c;则表单登录会关闭。此时可以启用httpBasic:

&#64;Override
httpSecurity.httpBasic(); // 开启httpBasic登录

这样浏览器访问时会弹窗提示输入用户名和密码。
若不需要表单登录&#xff0c;那么不附加formLogin()httpBasic()


登出

httpSecurity.logoutUrl()httpSecurity.addLogoutHandler()是冲突的&#xff0c;通常只用其中之一。
对于使用token且服务端不进行存储的情况&#xff0c;不需要请求服务端进行登出&#xff0c;直接由前端将token丢弃即可。


跨域

要解决跨域问题&#xff0c;通常需要&#xff1a;

httpSecurity.cors().and().csrf().disable();

其中&#xff1a;


  • cors()允许跨域资源访问。
  • csrf().disable()禁用跨域安全验证。

session创建规则

httpSecurity.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.IF_REQUIRED)&#xff1a;指的是设置session的创建策略。包含4个值&#xff1a;


  • ALWAYS&#xff1a;总是使用session。若没有session则创建。
  • NEVER&#xff1a;不创建session。但若应用中有其他地方创建了session&#xff0c;将使用。即用户登录时将不创建session。
  • IF_REQUIRED&#xff1a;默认值。如果有必要&#xff0c;则创建session。也就是用户登录成功时为其创建一个session。
  • STATELESS&#xff1a;不创建session&#xff0c;也不使用session。

Security默认使用的的策略为IF_REQUIRED。若使用token的方式&#xff0c;意味着不需要session&#xff0c;那么就需要设为STATELESS


自定义过滤器

可基于Security提供的抽象类Filter创建自定义Filter&#xff0c;然后调用HttpSecurity的成员方法来添加到filterChain中&#xff0c;例如&#xff1a;
定义Filter&#xff1a;

public class MyFilter extends OncePerRequestFilter {&#64;Overrideprotected void doFilterInternal(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, FilterChain filterChain) throws IOException, ServletException {filterChain.doFilter(httpServletRequest, httpServletResponse);}
}

然后添加到filterChain&#xff1a;

&#64;Override
protected void configure(HttpSecurity httpSecurity) throws Exception {// 自定义token过滤器httpSecurity.addFilterBefore(new MyFilter(), UsernamePasswordAuthenticationFilter.class)
}

添加的方法除了addFilterBefore()&#xff0c;还有addFilter()addFilterAfter()addFilterAt()等。


推荐阅读
  • Java Socket 关键参数详解与优化建议
    Java Socket 的 API 虽然被广泛使用,但其关键参数的用途却鲜为人知。本文详细解析了 Java Socket 中的重要参数,如 backlog 参数,它用于控制服务器等待连接请求的队列长度。此外,还探讨了其他参数如 SO_TIMEOUT、SO_REUSEADDR 等的配置方法及其对性能的影响,并提供了优化建议,帮助开发者提升网络通信的稳定性和效率。 ... [详细]
  • 本文介绍了如何利用Struts1框架构建一个简易的四则运算计算器。通过采用DispatchAction来处理不同类型的计算请求,并使用动态Form来优化开发流程,确保代码的简洁性和可维护性。同时,系统提供了用户友好的错误提示,以增强用户体验。 ... [详细]
  • 优化后的标题:深入探讨网关安全:将微服务升级为OAuth2资源服务器的最佳实践
    本文深入探讨了如何将微服务升级为OAuth2资源服务器,以订单服务为例,详细介绍了在POM文件中添加 `spring-cloud-starter-oauth2` 依赖,并配置Spring Security以实现对微服务的保护。通过这一过程,不仅增强了系统的安全性,还提高了资源访问的可控性和灵活性。文章还讨论了最佳实践,包括如何配置OAuth2客户端和资源服务器,以及如何处理常见的安全问题和错误。 ... [详细]
  • 在处理 XML 数据时,如果需要解析 `` 标签的内容,可以采用 Pull 解析方法。Pull 解析是一种高效的 XML 解析方式,适用于流式数据处理。具体实现中,可以通过 Java 的 `XmlPullParser` 或其他类似的库来逐步读取和解析 XML 文档中的 `` 元素。这样不仅能够提高解析效率,还能减少内存占用。本文将详细介绍如何使用 Pull 解析方法来提取 `` 标签的内容,并提供一个示例代码,帮助开发者快速解决问题。 ... [详细]
  • 深入探索HTTP协议的学习与实践
    在初次访问某个网站时,由于本地没有缓存,服务器会返回一个200状态码的响应,并在响应头中设置Etag和Last-Modified等缓存控制字段。这些字段用于后续请求时验证资源是否已更新,从而提高页面加载速度和减少带宽消耗。本文将深入探讨HTTP缓存机制及其在实际应用中的优化策略,帮助读者更好地理解和运用HTTP协议。 ... [详细]
  • 在安装并配置了Elasticsearch后,我在尝试通过GET /_nodes请求获取节点信息时遇到了问题,收到了错误消息。为了确保请求的正确性和安全性,我需要进一步排查配置和网络设置,以确保Elasticsearch集群能够正常响应。此外,还需要检查安全设置,如防火墙规则和认证机制,以防止未经授权的访问。 ... [详细]
  • 在对WordPress Duplicator插件0.4.4版本的安全评估中,发现其存在跨站脚本(XSS)攻击漏洞。此漏洞可能被利用进行恶意操作,建议用户及时更新至最新版本以确保系统安全。测试方法仅限于安全研究和教学目的,使用时需自行承担风险。漏洞编号:HTB23162。 ... [详细]
  • 本文介绍了一种自定义的Android圆形进度条视图,支持在进度条上显示数字,并在圆心位置展示文字内容。通过自定义绘图和组件组合的方式实现,详细展示了自定义View的开发流程和关键技术点。示例代码和效果展示将在文章末尾提供。 ... [详细]
  • 使用 ListView 浏览安卓系统中的回收站文件 ... [详细]
  • 在使用 Qt 进行 YUV420 图像渲染时,由于 Qt 本身不支持直接绘制 YUV 数据,因此需要借助 QOpenGLWidget 和 OpenGL 技术来实现。通过继承 QOpenGLWidget 类并重写其绘图方法,可以利用 GPU 的高效渲染能力,实现高质量的 YUV420 图像显示。此外,这种方法还能显著提高图像处理的性能和流畅性。 ... [详细]
  • 在PHP中实现腾讯云接口签名,以完成人脸核身功能的对接与签名配置时,需要注意将文档中的POST请求改为GET请求。具体步骤包括:使用你的`secretKey`生成签名字符串`$srcStr`,格式为`GET faceid.tencentcloudapi.com?`,确保参数正确拼接,避免因请求方法错误导致的签名问题。此外,还需关注API的其他参数要求,确保请求的完整性和安全性。 ... [详细]
  • 分享一款基于Java开发的经典贪吃蛇游戏实现
    本文介绍了一款使用Java语言开发的经典贪吃蛇游戏的实现。游戏主要由两个核心类组成:`GameFrame` 和 `GamePanel`。`GameFrame` 类负责设置游戏窗口的标题、关闭按钮以及是否允许调整窗口大小,并初始化数据模型以支持绘制操作。`GamePanel` 类则负责管理游戏中的蛇和苹果的逻辑与渲染,确保游戏的流畅运行和良好的用户体验。 ... [详细]
  • 在Java项目中,当两个文件进行互相调用时出现了函数错误。具体问题出现在 `MainFrame.java` 文件中,该文件位于 `cn.javass.bookmgr` 包下,并且导入了 `java.awt.BorderLayout` 和 `java.awt.Event` 等相关类。为了确保项目的正常运行,请求提供专业的解决方案,以解决函数调用中的错误。建议从类路径、依赖关系和方法签名等方面入手,进行全面排查和调试。 ... [详细]
  • 本文介绍了如何利用ObjectMapper实现JSON与JavaBean之间的高效转换。ObjectMapper是Jackson库的核心组件,能够便捷地将Java对象序列化为JSON格式,并支持从JSON、XML以及文件等多种数据源反序列化为Java对象。此外,还探讨了在实际应用中如何优化转换性能,以提升系统整体效率。 ... [详细]
  • Java中不同类型的常量池(字符串常量池、Class常量池和运行时常量池)的对比与关联分析
    在研究Java虚拟机的过程中,笔者发现存在多种类型的常量池,包括字符串常量池、Class常量池和运行时常量池。通过查阅CSDN、博客园等相关资料,对这些常量池的特性、用途及其相互关系进行了详细探讨。本文将深入分析这三种常量池的差异与联系,帮助读者更好地理解Java虚拟机的内部机制。 ... [详细]
author-avatar
刘诗宪668964
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有