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基本知识(一)的更多相关文章

  1. spring security基本知识(三) 过滤详细说明

    在我们前面的文章Spring Security 初识(一)中,我们看到了一个最简单的 Spring Security 配置,会要求所有的请求都要经过认证.但是,这并不是我们想要的,我们通常想自定义应用 ...

  2. spring security基本知识(二) 自定义认证

    配置自定义的用户存储 我们在 SecurityConfig 的配置类中 重写了 configure(AuthenticationManagerBuilder auth) 方法,我们可以通过 Authe ...

  3. spring security基本知识(四) WebSecurity

    1.创建一个Filter   现在web.xml文档中声明一个filter class="org".springframework.web.filter.DelegatingFil ...

  4. 【Spring】12、Spring Security 四种使用方式

    spring security使用分类: 如何使用spring security,相信百度过的都知道,总共有四种用法,从简到深为:1.不用数据库,全部数据写在配置文件,这个也是官方文档里面的demo: ...

  5. spring security的原理及教程

    spring security使用分类: 如何使用spring security,相信百度过的都知道,总共有四种用法,从简到深为:1.不用数据库,全部数据写在配置文件,这个也是官方文档里面的demo: ...

  6. [转]spring security的原理及教程

    Authentication:认证     spring security使用分类: 如何使用spring security,相信百度过的都知道,总共有四种用法,从简到深为:1.不用数据库,全部数据写 ...

  7. Spring security 知识笔记【自定义登录页面】

    一.引入依赖 <dependency> <groupId>org.springframework.boot</groupId> <artifactId> ...

  8. Spring security 知识笔记【入门】

    一.生成spring boot项目文件 二.pom文件如下 <?xml version="1.0" encoding="UTF-8"?> <p ...

  9. spring security oauth2.0 实现

    oauth应该属于security的一部分.关于oauth的的相关知识可以查看阮一峰的文章:http://www.ruanyifeng.com/blog/2014/05/oauth_2_0.html ...

随机推荐

  1. UI自动化关于图片验证码识别的解决方法

    def __save_screenshot(self): self.driver.save_screenshot('full_snap.png') self.page_snap_obj = Image ...

  2. activiti随笔记录

    核心组件介绍 关键对象 1.      Deployment:流程部署对象,部署一个流程时创建. 2.      ProcessDefinitions:流程定义,部署成功后自动创建. 3.       ...

  3. oracle分页排序,点击下一页数据不刷新

    oracle数据库中,如果每一页的最后一条和次页第一条数据的排序字段重复,会导致排序混乱,出现点击下一页数据不刷新的现象,所以一般排序至少选择一个相对唯一的字段.在前端页面可以输入排序条件的场景中,最 ...

  4. 什么是token?你是怎么理解token?

    1.Token的引入: Token是在客户端频繁向服务端请求数据,服务端频繁的去数据库查询用户名和密码并进行对比,判断用户名和密码正确与否,并作出相应提示,在这样的背景下,Token便应运而生. 2. ...

  5. switch-case的选择用法

    企业发放的奖金根据利润提成.利润I低于或等于100000元的,奖金可提0.1:利润高于100000元,低于200000(100000<I<=200000)时,低于100000元的部分按10 ...

  6. Java内存溢出

    中间件应用Java内存溢出常见的三种情况: 1.OutOfMemoryError: Java heap space 2.OutOfMemoryError: PermGen space 3.OutOfM ...

  7. 【CUDA】CUDA框架介绍

    引用 出自Bookc的博客,链接在此http://bookc.github.io/2014/05/08/my-summery-the-book-cuda-by-example-an-introduct ...

  8. Akka系列(九):Akka分布式之Akka Remote

    前言.... Akka作为一个天生用于构建分布式应用的工具,当然提供了用于分布式组件即Akka Remote,那么我们就来看看如何用Akka Remote以及Akka Serialization来构建 ...

  9. CDH的ntp时间同步

    云服务器: ntpq -p ntpdate -u 10.52.255.1  #手动同步 自建NTP服务器: https://www.cnblogs.com/yinzhengjie/p/9480665. ...

  10. idea常用快捷键列表

    在使用IntelliJ Idea的时候,使用快捷键是必不可少的.掌握一些常用的快捷键能大大提高我们的开发效率.有些快捷键可以熟练的使用,但是还有另外一些快捷键虽然很好用,但是由于因为没有形成使用习惯或 ...