Spring Boot2 总结(二) Spring Security的基本配置
Spring Boot对Spring Security提供了自动化配置方案,同时这也是在Spring Boot项目中使用Spring Security的优势,因此Spring Security整合进Spring Boot项目中是非常容易的。
一.Spring Security 的基本用法
1.1 创建项目,添加依赖
对应依赖如下:
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-security</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency>
1.2 添加一个controller接口
@GetMapping("/hello")public String hello(){return "hello everyone!";}
1.3 启动项目进行测试
启动后,Spring Security 默认的用户名为user,密码是每次启动项目启动的时候随机生成,如图:
项目启动日志中可以看到生成的默认密码,登录成功之后,就可以访问之前的接口了。
1.4 配置用户名和密码
当用户需要自己的账号和密码时,可以在application.properties配置文件中配置默认的用户名,密码以及用户角色等,相关配置如下:
spring.security.user.name=jiangbin
spring.security.user.password=123456
spring.security.user.roles=admin
1.5 基于内存的认证
开发者可以继承WebSecurityConfigureAdapter实现Spring Security更多的自定义配置,例如基于内存的配置,配置如下:
@Configuration
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {/*** spring security 5.x 引入了多种密码加密,开发者必须引入一种* 这里使用NoOpPasswordEncoder,即不对密码进行加密* @return*/@BeanPasswordEncoder passwordEncoder() {return new BCryptPasswordEncoder();}/*** 基于内存的认证* @param auth* @throws Exception*/@Overrideprotected void configure(AuthenticationManagerBuilder auth) throws Exception {auth.inMemoryAuthentication().withUser("root").password("123456").roles("ADMIN", "DBA").and().withUser("admin").password("123456").roles("ADMIN", "USER").and().withUser("jiangbin").password("123456").roles("USER");}
继承WebSecurityConfigurerAdapter,并重写configure(AuthenticationManagerBuilder auth)方法,在这个方法中配置三个用户以及他们的密码和角色。
注:基于内存的认证在配置角色的时候不需要添加前缀"ROLE_",然而在基于数据库的认证中配置角色时需要添加前缀"ROLE_"。
1.5 HttpSecurity
如上已经实现了认证功能,但是受保护的资源都是默认的,而且不能更具实际情况进行角色管理,如果要实现这些功能,就可以实现WebSecurityConfigurerAdapter中另外一个方法,代码如下:
/*** 指定受保护的资源 和 根据实际情况进行角色管理* @param http* @throws Exception*/@Overrideprotected void configure(HttpSecurity http) throws Exception {http.authorizeRequests().antMatchers("/admin/**").hasRole("ADMIN").antMatchers("/user/**").hasAnyRole("ADMIN", "USER").antMatchers("/dba/**").access("hasRole('ADMIN') and hasRole('DBA')").anyRequest().authenticated().and().formLogin().loginProcessingUrl("/login").permitAll() //表示和登录相关的接口都不要认证即可访问.and().csrf().disable();}
authorizeRequests()方法开启HttpSecurity配置。9-14行表示用户访问某种模式的Url必须具备什么样的角色,如访问"/admin/**“模式的Url必须具备ADMIN的角色。15-16行表示除了前面定义的URl模式之外,用户访问其他的模式Url必须登录才能访问。18行开启表单登录,19行表示登录接口为”/login",主要方便移动端和Ajax调用登录接口,登录参数中用户命名必须为username,密码必须命名为password。permitAll()方法表示所有与登录有关的接口都不需要认证即可访问。22-23行表示关闭csrf。
1.6表单登录详细配置
登录表单一直使用Spring Security提供的页面,登录成功后也是默认的页面跳转,如今前后端分离开始成为主流,在前后端的开发中,数据是通过Json进行的,此时登录成功将不在进行页面跳转,而实通过一段JSON提示。
.and().formLogin().loginProcessingUrl("/login").usernameParameter("name").passwordParameter("passwd").successHandler(new AuthenticationSuccessHandler() {@Overridepublic void onAuthenticationSuccess(HttpServletRequest req, HttpServletResponse resp, Authentication auth) throws IOException, ServletException {Object principal = auth.getPrincipal(); //获取登录用户的信息resp.setContentType("application/json;charset=utf-8");PrintWriter out = resp.getWriter();resp.setStatus(200);Map<String, Object> map = new HashMap<>();map.put("status", 200);map.put("msg", principal);ObjectMapper om = new ObjectMapper();String s = om.writeValueAsString(map);out.write(s);out.flush();out.close();}}).failureHandler(new AuthenticationFailureHandler() {@Overridepublic void onAuthenticationFailure(HttpServletRequest req, HttpServletResponse resp, AuthenticationException e) throws IOException, ServletException {resp.setContentType("application/json;charset=utf-8");PrintWriter out = resp.getWriter();resp.setStatus(401);Map<String, Object> map = new HashMap<>();map.put("status", 401);if (e instanceof LockedException) {map.put("msg", "账户被锁定,登录失败");} else if (e instanceof BadCredentialsException) {map.put("msg", "账户或密码输入错误,登陆失败");} else if (e instanceof CredentialsExpiredException) {map.put("msg", "密码已过期,登陆失败");} else if (e instanceof AccountExpiredException) {map.put("msg", "账户已过期,登录失败");} else if (e instanceof DisabledException) {map.put("msg", "账户被禁用");}ObjectMapper om = new ObjectMapper();String s = om.writeValueAsString(map);out.write(s);out.flush();out.close();}}).permitAll() //表示和登录相关的接口都不要认证即可访问.and()
successHandler()方法表示登录成功的处理逻辑,用户登录成功可以返回一个页面,也可以返回一段JSON数据,这里我们返回的是一段JSON数据,在onAuthenticationSuccess()方法中参数Authentication表示获取当前登录用户的信息。
failureHandler()方法表示登录失败的处理逻辑,登录失败可以通过参数AuthenticationException获取登录失败的原因。
1.7注销登录配置
.and().logout() //开启注销配置.logoutUrl("/logout") //注销登录请求Url.clearAuthentication(true) //是否清除身份认证.invalidateHttpSession(true) //是否使Session失效.addLogoutHandler(new LogoutHandler() { //可以完成一些数据清除工作@Overridepublic void logout(HttpServletRequest req, HttpServletResponse resp, Authentication auth) {}}).logoutSuccessHandler(new LogoutSuccessHandler() { //处理注销成功后的业务逻辑。如返回一段json或跳转到登录页面@Overridepublic void onLogoutSuccess(HttpServletRequest req, HttpServletResponse resp, Authentication auth) throws IOException, ServletException {resp.setContentType("application/json;charset=utf-8");PrintWriter out = resp.getWriter();out.write("注销登录成功!");out.flush();out.close();}}).and()
1.8 多个HttpSecurity
业务比较复杂时,开发者可以配置多个HttpSecurity,实现对WebSecurityConfigurerAdapter的多次拓展,代码如下:
@Configuration
public class MultiHttpSecurityConfig {@BeanPasswordEncoder passwordEncoder() {return new BCryptPasswordEncoder();}@Autowiredpublic void configure(AuthenticationManagerBuilder auth) throws Exception {auth.inMemoryAuthentication().withUser("admin").password("$2a$10$qLDuJyeHKPjrcrmdeALpsODPyY694c3Pv7tRCMTjftOuShH2s1arC").roles("ADMIN", "USER").and().withUser("jiangbin").password("$2a$10$iKqkzWsAkos1xXIWmtvZb.zZTQ6qKHxnKsuPr2IIolX4Jv.Dfn/xW").roles("USER");}@Configuration@Order(1)public static class AdminHttpSecurityConfig extends WebSecurityConfigurerAdapter {@Overrideprotected void configure(HttpSecurity http) throws Exception {http.antMatcher("/admin/**").authorizeRequests().anyRequest().hasRole("ADMIN");}}@Configurationpublic static class OtherHttpSecurityConfig extends WebSecurityConfigurerAdapter {@Overrideprotected void configure(HttpSecurity http) throws Exception {http.authorizeRequests().anyRequest().authenticated().and().formLogin().loginProcessingUrl("/login").permitAll().and().csrf().disable();}}
}
实现多个HttpSecurity时,主类不要继承WebSecurityConfigurerAdapter,在主类中创建静态内部类继承WebSecurityConfigurerAdapter即可,同时在类上加上@Configration和@Order注解,@Order表示优先级,数字越小优先级越大,未加@Order注解的优先级最小。
1.9 密码加密
@BeanPasswordEncoder passwordEncoder() {return new BCryptPasswordEncoder(10);}
Spring Security提供了多种密码的加密方式,官方推荐使用 BCryptPasswordEncoder,它使用BCrypt强哈希函数,开发者在使用时可以提供strength和SecureRandom实例。strenth越大,密钥迭代的次数越多,密钥迭代次数为2^strength。Strength取值在4-31之间,默认为10。
1.10 方法安全
开发者可以通过注解来灵活的配置方法安全,如果要使用相关注解,首先需要@EnableGlobalMethodSecurity注解开启基于注解的安全配置。
@Configuration
@EnableGlobalMethodSecurity(prePostEnabled = true , securedEnabled = true) //开启方法安全配置
public class WebSecurityConfigWithGlobal {}
prePostEnabled = true会开启 @PreAuthorize和@PostAuthorize两个注解,@PreAuthorize注解会在方法执行之前进行验证,@PostAuthorize注解在方法执行之后进行验证。而securedEnabled = true会开启@Secured注解。
开启注解后,写一个Service进行测试。代码如下:
@Service
public class HelloService {@Secured("ROLE_ADMIN")public String admin(){return "hello admim";}@PreAuthorize("hasRole('Admin') and hasRole('DBA')")public String dba(){return "hello dba";}@PreAuthorize("hasAnyRole('ADMIN','USER','DBA')")public String user(){return "hello user";}
}
@Secured(“ROLE_ADMIN”)注解表示访问该方法需要ADMIN角色,这里需要在角色前加上前缀"ROLE_"。下面两个注解表示的意思也是如此。
Spring Boot2 总结(二) Spring Security的基本配置相关推荐
- Spring Boot2.x-10 基于Spring Boot 2.1.2 + Mybatis 2.0.0实现多数据源,支持事务
文章目录 概述 思路 步骤 Step1 多数据源配置文件applicaiton.yml Step2 初始化多个数据源 Step3 配置多个数据源 验证测试 支持事务 Step1 配置类中通过@Bean ...
- Spring Boot2.x-09 基于Spring Boot 2.1.2 + Mybatis使用自定义注解实现数据库切换
文章目录 概述 场景说明:读写分离 操作步骤 工程结构 Step1 自定义注解 Step2 数据源定义 Step3 配置文件配置数据源 Step4 数据源实例化DatasourceConfig Ste ...
- Spring 学习之 二----Spring创建对象的三种方式
最近在系统的学习Spring,现在就Spring的一些知识进行总结. 我们知道Spring是一个开放源代码的设计层面的框架,他主要解决的是业务逻辑层与其他各层之间松耦合的问题. Spring 有三个核 ...
- spring boot 学习(二)spring boot 框架整合 thymeleaf
spring boot 框架整合 thymeleaf spring boot 的官方文档中建议开发者使用模板引擎,避免使用 JSP.因为若一定要使用 JSP 将无法使用. 注意:本文主要参考学习了大神 ...
- Spring Boot系列二 Spring @Async异步线程池用法总结
转载 自 https://blog.csdn.net/hry2015/article/details/67640534 1. TaskExecutor Spring异步线程池的接口类,其实质是java ...
- Spring Data 系列(二) Spring+JPA入门(集成Hibernate)
通过[Spring Data 系列(一) 入门]的介绍,通过对比的方式认识到Spring提供的JdbcTemplate的强大功能.通过使用JdbcTemplate,操作数据库,不需要手动处理Conne ...
- SpringSecurity权限管理框架系列(六)-Spring Security框架自定义配置类详解(二)之authorizeRequests配置详解
1.预置演示环境 这个演示环境继续沿用 SpringSecurit权限管理框架系列(五)-Spring Security框架自定义配置类详解(一)之formLogin配置详解的环境. 2.自定义配置类 ...
- 7. Spring Boot2.5 安全机制与 REST API 身份验证实战
文章目录 Spring Boot2.5 安全机制与 RESTAPI 身份验证实战 一.Java Spring Boot 2.5 安全机制 Java Spring Boot 2.0 安全机制 安全漏洞 ...
- Spring Boot2.x-12 Spring Boot2.1.2中Filter和Interceptor 的使用
文章目录 Interceptor 拦截器 拦截器中方法的执行流程 传统项目拦截器的配置 Spring Boot2.1.2整合拦截器Interceptor 示例 Step1 实现HandlerInter ...
最新文章
- 怎么切换用户_走进通信:4G手机跟基站是怎么“交流”的
- 颠覆农业思维-国际农民丰收节贸易会·万祥军:大粮食概念
- oracle查看字典结构体,Oracle-17-数据字典查看约束信息
- Node.js~ioredis处理耗时请求时连接数瀑增
- 【玩转树莓派】使用 sinopia 搭建私有 npm 服务器
- 查询程序崩溃日志_PC 崩溃报告途径 amp; 临时解决方法
- P2770 航空路线问题(网络流)
- js原型、原型链、作用链、闭包全解
- 前端如何快速上手 Web 3D 游戏的开发
- 将序列设置为字段的默认值 - oracle
- Acwing:最长回文子串
- 织梦php 文章采集规则,织梦输入网址采集单个网页功能发布 不需要写采集规则一键采集...
- 搜索引擎 —海量数据搜索
- 7-4 华氏度转摄氏度 (5分) java
- Millet谷仓区块链和电子商务及Token相结合的产物
- html5 调用本地街景,H5案例分享:在移动端调用腾讯街景
- 草丛效果-shader forge
- golang的http
- Python开发过哪些知名网站和游戏?
- Windows编译libjpeg库