Spring Security修炼手册(一)————初识Security


声明:本文转载自https://my.oschina.net/u/3637243/blog/1820408,转载目的在于传递更多信息,仅供学习交流之用。如有侵权行为,请联系我,我会及时删除。

    在以前做东西的时候,对于认证鉴权的框架技术选型,通常使用Apache Shiro,可能是接触比较早,感觉用起来比较方便的原因,知道最近接了一个好大好大的项目分布式应用+大数据数据库+私有IaaS云+PaaS,埋头苦学一星期,算是吃透了Spring Security的一半,那么一是为了记录在学习过程中的知识点,二是为了让没有接触过安全框架,或者还在使用数据库,自己写Filter比较原始方式做权限控制的朋友提供一个学习的参考。那么废话不说太多,下面开始一步一步来。

  一、初识Spring Security

        首先看名字就可以看出来,这个框架出自于Pivotal 的Spring系列。Spring Security 提供了基于javaEE的企业应用,全面的安全服务。 大家使用Spring Secruity的原因有很多,但是大部分都是发现了由于javaEE的Servlet规范或EJB规范中的安全功能缺乏典型企业应用场景所需的深度。 那么Security提供的 “认证”和“授权”(或者访问控制) 是整个框架也是本系列博客所要讲解的重要内容。

二、引入Security依赖

    Security官方链接:https://projects.spring.io/spring-security/

    打开你的IED,在Maven坐标如下:想使用其他版本请去如上链接,如果你之前接触过Spring IO那么无需指定Version.

<dependencies>     <dependency>         <groupId>org.springframework.security</groupId>         <artifactId>spring-security-web</artifactId>         <version>5.0.5.RELEASE</version>     </dependency> </dependencies>

  Gradle如下:

dependencies {     compile 'org.springframework.security:spring-security-web:5.0.5.RELEASE' }

三、Security的基本认证功能的使用

    首先明确一个事情,Spring Security所有提供给开发者的认证和鉴权功能都是基于过滤器链的,而我看到的大部分讲解Security的博客和资料中,却很少提及每个功能作用的过滤器是谁?过滤器的执行流程是怎么样的!我之前在学习Docker和K8S的时候买的一本书讲解的非常透彻,作者不仅仅在讲怎么用!而是从:是什么?怎么用?为什么?这三方面来说,因此我会在文中通过Debug或流程图,为大家深入的讲解这款框架的东西。

    3.1、HttpBasic认证

        那么当你引入了Security的依赖后,无需做其他任何的事情,启动项目,访问的时候你就会发现你的应用已经有了一个基本的认证功能,其实前面说的话不是完全正确的,由于笔者之前使用的Spring Boot版本为1.5,依赖的Security 4.X版本,所以无需任何配置,启动项目访问则会弹出默认的httpbasic认证,那么本次Demo是基于security5.X ,Spring Boot2.X版本去做的,经过我翻阅官方文档和Spring Boot2.X的properties,在这个5.X的版本中已经将默认的认证方式更改为表单认证,并且security.basic.enabled属性同样是过期了的。

                                        

    下面的图是官方给出的属性配置,已经无security.basic.enabled

    

        在这里笔者十分负责任的说,如果想开启httpbasic认证,需要在配置类中进行配置才可以,亲测通过properties配置不生效,开启httpbasic认证的代码如下:

import org.springframework.context.annotation.Configuration; import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter ; @Configuration public class SecurityConfig extends WebSecurityConfigurerAdapter{ 	 	@Override 	protected void configure(HttpSecurity http) throws Exception { 		 		http 		   .httpBasic()//开启httpbasic认证 		.and() 		   .authorizeRequests()//Security表达式 	             .anyRequest().authenticated();//所有请求都需要认证 	}  }

    启动项目,在启动的时候会发现控制台有如下输出,这个字符串就是Security默认生成的认证密码。

    访问应用,弹出httpbasic,通过生成的默认密码进行认证,不过这种方式基本不太会使用,不着重介绍。

    3.2、表单认证

        表单认证是大部分业务场景中都需要使用的一种认证方式,那么如何配置,又有哪些可配置的呢?看如下代码:

import org.springframework.context.annotation.Configuration; import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurer Adapter;  @Configuration public class SecurityConfig extends WebSecurityConfigurerAdapter{ 	 	 	@Override 	protected void configure(HttpSecurity http) throws Exception { 		 		http 		.formLogin() 			.loginPage("/loginPage.html")//用户未认证时,转跳到认证的页面 			.loginProcessingUrl("/toLogin")//form中action的地址,也就是处理认证请求的URL	 			.usernameParameter("UM")//form中用户名密码的name名 			.passwordParameter("PW") 			.defaultSuccessUrl("/index")//认证成功后默认转跳的URL 		.and() 		.authorizeRequests() 			.antMatchers("/loginPage.html","/toLogin").permitAll()//最后不要忘记将自定义的                                                                            //如上不需要认证的URL加进来 			.anyRequest().authenticated(); 	}  }

我们访问任意需要认证的URL,发现会自动转跳到配置的认证页面。

 我们暂时先使用内存用户,在properties中配置一个admin用户,模拟登录。

 登陆后,自动转跳到index的controller中,对了!如果你使用了自己的登录页面,记得将CSRF防护功能关掉哦,否则你讲无法进行认证。

四、基于Spring的配置

    那么通过以上代码的讲解,你应该对于认证功能的基本使用有了一定的了解,但是上面的代码中有一个开发界非常难以容忍的问题,就是含有大量的硬编码!!!那么我们如何解决的?

首先我们创建三个类,分别叫:SecurityProperties、ToLoginProperties、LoginProperties,代码分别如下:

public class LoginProperties { 	 	private String loginPage = "/loginPage.html"; 	 	private String loginProcessingUrl = "/toLogin"; 	 	private String usernameParameter = "UM"; 	 	private String passwordParameter = "PW"; 	 	private String defaultSuccessUrl = "/index";  	public String getLoginPage() { 		return loginPage; 	}  	public void setLoginPage(String loginPage) { 		this.loginPage = loginPage; 	}  	public String getLoginProcessingUrl() { 		return loginProcessingUrl; 	}  	public void setLoginProcessingUrl(String loginProcessingUrl) { 		this.loginProcessingUrl = loginProcessingUrl; 	}  	public String getUsernameParameter() { 		return usernameParameter; 	}  	public void setUsernameParameter(String usernameParameter) { 		this.usernameParameter = usernameParameter; 	}  	public String getPasswordParameter() { 		return passwordParameter; 	}  	public void setPasswordParameter(String passwordParameter) { 		this.passwordParameter = passwordParameter; 	}  	public String getDefaultSuccessUrl() { 		return defaultSuccessUrl; 	}  	public void setDefaultSuccessUrl(String defaultSuccessUrl) { 		this.defaultSuccessUrl = defaultSuccessUrl; 	} 	 	 } 
public class ToLoginProperties { 	 	private LoginProperties loginProperties = new LoginProperties();  	public LoginProperties getLoginProperties() { 		return loginProperties; 	}  	public void setLoginProperties(LoginProperties loginProperties) { 		this.loginProperties = loginProperties; 	}  } 
import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.stereotype.Component;  @Component @ConfigurationProperties(prefix = "jy.security") public class SecurityProperties {  	private ToLoginProperties toLoginProperties = new ToLoginProperties();  	public ToLoginProperties getToLoginProperties() { 		return toLoginProperties; 	}  	public void setToLoginProperties(ToLoginProperties toLoginProperties) { 		this.toLoginProperties = toLoginProperties; 	} 	 } 

    通过以上代码,我们就可以读取到配置文件中,以“jy.security”开头的属性,并将属性对应的值注入到其中,这样当我们配置了对应属性的时候,值即被替换,未配置的时候则走我们的默认值。

然后我们把securityconfig类在修改一下,不在使用硬编码,而是将SecurityProperties类注入。

import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Configuration; import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;  import com.spring.demo.peoperties.SecurityProperties;  @Configuration public class SecurityConfig extends WebSecurityConfigurerAdapter{ 	 	@Autowired 	private SecurityProperties securityProperties; 	 	@Override 	protected void configure(HttpSecurity http) throws Exception { 		 		http 			.formLogin() 				.loginPage(securityProperties.getToLoginProperties().getLoginProperties().getLoginPage())//用户未认证时,转跳到认证的页面 				.loginProcessingUrl(securityProperties.getToLoginProperties().getLoginProperties().getLoginProcessingUrl())//form中action的地址,也就是处理认证请求的URL	 				.usernameParameter(securityProperties.getToLoginProperties().getLoginProperties().getUsernameParameter())//form中用户名密码的name名 				.passwordParameter(securityProperties.getToLoginProperties().getLoginProperties().getPasswordParameter()) 				.defaultSuccessUrl(securityProperties.getToLoginProperties().getLoginProperties().getDefaultSuccessUrl())//认证成功后默认转跳的URL 		.and() 		.authorizeRequests() 			.antMatchers(securityProperties.getToLoginProperties().getLoginProperties().getLoginPage(), 					     securityProperties.getToLoginProperties().getLoginProperties().getLoginProcessingUrl()).permitAll() 			.anyRequest().authenticated() 		.and() 			.csrf().disable() 			; 	} 	 	  } 

    最后我们做一个测试,证明通过配置文件的方式,可以对我们的配置类修改,我们修改未认证时转跳的认证页面的URL为“/loginTest”

重启项目,访问/index,结果如下:404是由于我根本没写这个页面,但已经可以证明我们的配置生效,避免了硬编码的问题

 在下一篇博客里,我会介绍自定义身份认证和一些处理器的用法及源码,敬请关注!

本文发表于2018年05月29日 14:00
(c)注:本文转载自https://my.oschina.net/u/3637243/blog/1820408,转载目的在于传递更多信息,并不代表本网赞同其观点和对其真实性负责。如有侵权行为,请联系我们,我们会及时删除.

阅读 2141 讨论 0 喜欢 0

抢先体验

扫码体验
趣味小程序
文字表情生成器

闪念胶囊

你要过得好哇,这样我才能恨你啊,你要是过得不好,我都不知道该恨你还是拥抱你啊。

直抵黄龙府,与诸君痛饮尔。

那时陪伴我的人啊,你们如今在何方。

不出意外的话,我们再也不会见了,祝你前程似锦。

这世界真好,吃野东西也要留出这条命来看看

快捷链接
网站地图
提交友链
Copyright © 2016 - 2021 Cion.
All Rights Reserved.
京ICP备2021004668号-1