spring security基本知识(一)
spring security基本知识(一)
Spring Security是为基于Spring的应用程序提供声明式安全保护的安全 性框架。Spring Security提供了完整的安全性解决方案,它能够在Web 请求级别和方法调用级别处理身份认证和授权。因为基于Spring框 架,所以Spring Security充分利用了依赖注入(dependency injection, DI)和面向切面的技术。Spring Security借助一系列Servlet Filter来提供各种安全性功能。但是这一系列Servlet Filter并不需要我们在web.xml或WebApplicationInitializer中配置多个Filter。
要实现自定义security配置,最核心的就是重写“WebSecurityConfigurerAdapter”。
相关解释说明
注解 @EnableWebSecurity
在 Spring boot 应用中使用 Spring Security,用到了 @EnableWebSecurity
注解。
抽象类 WebSecurityConfigurerAdapter
一般情况,会选择继承 WebSecurityConfigurerAdapter
类。WebSecurityConfigurerAdapter
提供了一种便利的方式去创建 WebSecurityConfigurer
的实例,只需要重写 WebSecurityConfigurerAdapter
的方法,即可配置拦截什么URL、设置什么权限等安全控制
WebSecurityConfigurerAdapter里的重要方法:
1、configure(HttpSecurity)通过重载,配置如何通过拦截器保护请求。
2、configure(AuthenticationManagerBuilder)通过重在配置user-detail 服务。
3、configure(WebSecurity)通过重载,配置Spring Security的Filter链
详细说明:
1、 configure(HttpSecurity)
我们知道,在引入security依赖后,启动项目在登陆时就会出现弹窗让我们来输入账号密码。那是因为WebSecurityConfigurerAdapter自身已经实现了一套安全过滤,但这并不是我们想要的。先来看一下WebSecurityConfigurerAdapter的configure(HttpSecurity) 方法如下。HttpSecurity 实现了一个 HttpSecurityBuilder 接口,这是一个构造器接口,因此可以使用构造器典型的链式调用风格.通过调用authorizeRequests()和 anyRequest()。
@Override
public void configure(HttpSecurity http) throws Exception {
http.authorizeRequests().anyRequest().authenticated()
.and().formLogin()
.and().httpBasic();
}
我们需要自定义符合我们需求的安全过滤体系,重载后的方法如下。
/**
* 匹配 "/" 路径,不需要权限即可访问
* 匹配 "/user" 及其以下所有路径,都需要 "USER" 权限
* 登录地址为 "/login",登录成功默认跳转到页面 "/user"
* 退出登录的地址为 "/logout",退出成功后跳转到页面 "/login"
* 默认启用 CSRF
*/
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/").permitAll()
.antMatchers("/user/**").hasRole("USER")
.and().formLogin().loginPage("/login").defaultSuccessUrl("/user")
.and().logout().logoutUrl("/logout").logoutSuccessUrl("/login");
}
当然,HttpSecurity的方法还有很多,比如csrf()、sessionManagement()等,后续再详细说明。
2、configure(AuthenticationManagerBuilder)
Spring Security非常灵活,能够基于各种数据存储来认证用户。它内置了许多常见的用户存储场景。如: 内存,关系型数据库,以及LDAP。当然,我们也可以编写并插入自定义的用户存储实现。
查看AuthenticationManagerBuilder源码,有如下方法:
public InMemoryUserDetailsManagerConfigurer<AuthenticationManagerBuilder> inMemoryAuthentication() throws Exception {
return (InMemoryUserDetailsManagerConfigurer)this.apply(new InMemoryUserDetailsManagerConfigurer());
}//内存 public JdbcUserDetailsManagerConfigurer<AuthenticationManagerBuilder> jdbcAuthentication() throws Exception {
return (JdbcUserDetailsManagerConfigurer)this.apply(new JdbcUserDetailsManagerConfigurer());
}//jdbc public <T extends UserDetailsService> DaoAuthenticationConfigurer<AuthenticationManagerBuilder, T> userDetailsService(T userDetailsService) throws Exception {
this.defaultUserDetailsService = userDetailsService;
return (DaoAuthenticationConfigurer)this.apply(new DaoAuthenticationConfigurer(userDetailsService));
}//用户自定义 public LdapAuthenticationProviderConfigurer<AuthenticationManagerBuilder> ldapAuthentication() throws Exception {
return (LdapAuthenticationProviderConfigurer)this.apply(new LdapAuthenticationProviderConfigurer());
}//ldap
1)使用基于内存的用户存储
@Override
public void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.inMemoryAuthentication()
.withUser("user_name1").password("123456").roles("USER")
.and()
.withUser("user_name1").password("123456").roles("ADMIN");
}
2)基于JDBC
@Autowired
private javax.sql.DataSource dataSource; //基于数据库表的用户存储
@Override
public void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.jdbcAuthentication()
.dataSource(dataSource); }
在这里我们只需要配置一个dataSource即可,这样就可以访问关系型数据库了。其中 dataSource是通过自动装配的技巧得到的。在springboot下 dataSource 是自动装配的。我们只需要引入如下依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency> <dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
并在appliciation.properties 中配置spring.datasource 相关属性即可。
spring.datasource.driverClassName=com.mysql.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/test?prepStmtCacheSize=517&cachePrepStmts=true&autoReconnect=true&characterEncoding=utf-8&allowMultiQueries=true
spring.datasource.username=root
spring.datasource.password=root
Spring Boot就会使用该配置创建一个DataSource。并装配为Spring的一个bean。因此我们可以直接使用 @Autowired 进行注入。
好了,直到目前为止,对基于数据库的用户存储已经配置完毕,你可能回想,那既然基于数据库了,肯定要在数据库创建相应的表了。那表结构又是怎么样的呢?
auth.jdbcAuthentication()方法返回的是JdbcUserDetailsManagerConfigurer,他除了dataSource(dataSource)方法还有,
public JdbcUserDetailsManagerConfigurer<B> usersByUsernameQuery(String query) throws Exception {
this.getUserDetailsService().setUsersByUsernameQuery(query);
return this;
} public JdbcUserDetailsManagerConfigurer<B> authoritiesByUsernameQuery(String query) throws Exception {
this.getUserDetailsService().setAuthoritiesByUsernameQuery(query);
return this;
} public JdbcUserDetailsManagerConfigurer<B> groupAuthoritiesByUsername(String query) throws Exception {
JdbcUserDetailsManager userDetailsService = this.getUserDetailsService();
userDetailsService.setEnableGroups(true);
userDetailsService.setGroupAuthoritiesByUsernameQuery(query);
return this;
}
这几个方法。他们在JdbcDaoImpl中有默认的SQL。
private String authoritiesByUsernameQuery = "select username,authority from authorities where username = ?";
private String groupAuthoritiesByUsernameQuery = "select g.id, g.group_name, ga.authority from groups g, group_members gm, group_authorities ga where gm.username = ? and g.id = ga.group_id and g.id = gm.group_id";
private String usersByUsernameQuery = "select username,password,enabled from users where username = ?";
当然我们也可以根据业务自己定义SQL
@Autowired
private DataSource dataSource; //基于数据库表的用户存储
@Override
public void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.jdbcAuthentication()
.dataSource(dataSource)
.usersByUsernameQuery("select username,password,enabled,email from users where username=?")
.authoritiesByUsernameQuery("select username,authority from authorities where username = ?")
.groupAuthoritiesByUsername("select g.id, g.group_name, ga.authority from groups g, group_members gm, group_authorities ga where gm.username = ? and g.id = ga.group_id and g.id = gm.group_id");
}
我们就是要依据这些SQL来创建表格,或者可以反过来说。我们定义好表格后使用自定义的SQL。
spring security基本知识(一)的更多相关文章
- spring security基本知识(三) 过滤详细说明
在我们前面的文章Spring Security 初识(一)中,我们看到了一个最简单的 Spring Security 配置,会要求所有的请求都要经过认证.但是,这并不是我们想要的,我们通常想自定义应用 ...
- spring security基本知识(二) 自定义认证
配置自定义的用户存储 我们在 SecurityConfig 的配置类中 重写了 configure(AuthenticationManagerBuilder auth) 方法,我们可以通过 Authe ...
- spring security基本知识(四) WebSecurity
1.创建一个Filter 现在web.xml文档中声明一个filter class="org".springframework.web.filter.DelegatingFil ...
- 【Spring】12、Spring Security 四种使用方式
spring security使用分类: 如何使用spring security,相信百度过的都知道,总共有四种用法,从简到深为:1.不用数据库,全部数据写在配置文件,这个也是官方文档里面的demo: ...
- spring security的原理及教程
spring security使用分类: 如何使用spring security,相信百度过的都知道,总共有四种用法,从简到深为:1.不用数据库,全部数据写在配置文件,这个也是官方文档里面的demo: ...
- [转]spring security的原理及教程
Authentication:认证 spring security使用分类: 如何使用spring security,相信百度过的都知道,总共有四种用法,从简到深为:1.不用数据库,全部数据写 ...
- Spring security 知识笔记【自定义登录页面】
一.引入依赖 <dependency> <groupId>org.springframework.boot</groupId> <artifactId> ...
- Spring security 知识笔记【入门】
一.生成spring boot项目文件 二.pom文件如下 <?xml version="1.0" encoding="UTF-8"?> <p ...
- spring security oauth2.0 实现
oauth应该属于security的一部分.关于oauth的的相关知识可以查看阮一峰的文章:http://www.ruanyifeng.com/blog/2014/05/oauth_2_0.html ...
随机推荐
- 自定义Spring-Boot @Enable注解
Spring-Boot中有很多Enable开头的注解,通过添加注解来开启一项功能,如 其原理是什么?如何开发自己的Enable注解? 1.原理 以@EnableScheduling为例,查看其源码,发 ...
- LeetCode.1013-分割数组为三个和相同的部分
这是小川的第378次更新,第406篇原创 01 看题和准备 今天介绍的是LeetCode算法题中Easy级别的第240题(顺位题号是1013).给定一个整数数组A,当且仅当我们可以将数组分成具有相等和 ...
- P4878 [USACO05DEC] 布局
题面lalala 这居然是个紫题???原谅我觉得这题是模板... 这个这个,这题的算法呢其实是一个叫差分约束的东西,也是今天下午我们机房的重点,如果不知道这个差分约束是个啥的人呢,自行百度一下谢谢.. ...
- 修改了Mysql密码后连接不到服务且无报错信息解决方法以及修改密码方法
安装MYSQL后更改了root的密码后用 net start mysql 启动时出现:无法启动,无报错信息 使用以下命令:1.管理员方式cmd进入mysql安装目录的bin目录下2.执行命令:mysq ...
- 第六周作业&实验报告四
一.实验目的 (1)掌握类的继承 (2)变量的继承和覆盖,方法的继承,重载和覆盖的实现: 二.实验的内容 (1)根据下面的要求实现圆类Circle. 1.圆类Circle的成员变量:radius表示圆 ...
- AttributeError: 'dict' object has no attribute 'status_code'
前端AJAX请求数据,提示错误:“AttributeError: 'dict' object has no attribute 'status_code'”. 原因:是提示返回对象dict没有“sta ...
- 【Linux 驱动】简单字符设备驱动架构(LED驱动)
本文基于icool210开发板,内核版本:linux2.6.35: 驱动代码: (1)头文件:led.h #ifndef __LED_H__ #define __LED_H__ #define LED ...
- 小记---------手动执行脚本正常执行,使用crontab定时执行时 不执行
可能出现的原因就是因为crontab不会从用户的/etc/profile文件中读取环境变量,所以就出现 使用定时crontab执行时 无法执行 抛错 所以在使用crontab 定时执行脚本时 在脚本 ...
- 并发之AQS原理(二) CLH队列与Node解析
并发之AQS原理(二) CLH队列与Node解析 1.CLH队列与Node节点 就像通常医院看病排队一样,医生一次能看的病人数量有限,那么超出医生看病速度之外的病人就要排队. 一条队列是队列中每一个人 ...
- 【一个蒟蒻的挣扎】LCA (倍增)
#include<cstdio> #include<iostream> #include<cstring> using namespace std; struct ...