SpringBoot——Spring Security 框架

优质博文:IT-BLOG-CN

一、Spring Security 简介

Spring Security是一个能够为基于Spring的企业应用系统提供声明式的安全访问控制解决方案的安全框架。它提供了一组可以在Spring应用上下文中配置的 Bean,充分利用了Spring IoCDI(控制反转 Inversion of ControlDIDependency Injection 依赖注入)和AOP(面向切面编程)功能,为应用系统提供声明式的安全访问控制功能,减少了为企业系统安全控制编写大量重复代码的工作。

二、Spring Security 入门Demo

【1】创建Maven工程(war形式):spring-security-demo
【2】修改pom.xml目录,如下:


<properties>
  <junit.version>4.12junit.version>
  <spring.version>4.2.4.RELEASEspring.version>
  <pagehelper.version>4.0.0pagehelper.version>
  <servlet-api.version>2.5servlet-api.version>
  <dubbo.version>2.8.4dubbo.version>
  <zookeeper.version>3.4.7zookeeper.version>
  <zkclient.version>0.1zkclient.version>		
  <mybatis.version>3.2.8mybatis.version>
  <mybatis.spring.version>1.2.2mybatis.spring.version>
  <mybatis.paginator.version>1.2.15mybatis.paginator.version>
  <mysql.version>5.1.32mysql.version>		
  <druid.version>1.0.9druid.version>
  <commons-fileupload.version>1.3.1commons-fileupload.version>
  <freemarker.version>2.3.23freemarker.version>
  <activemq.version>5.11.2activemq.version>
  <security.version>3.2.3.RELEASEsecurity.version>		
  <solrj.version>4.10.3solrj.version>
  <ik.version>2012_u6ik.version>		
properties>
<dependencies>
	<dependency>
		<groupId>org.springframeworkgroupId>
		<artifactId>spring-coreartifactId>
		<version>${spring.version}version>
	dependency>
	<dependency>
		<groupId>org.springframeworkgroupId>
		<artifactId>spring-webartifactId>
		<version>${spring.version}version>
	dependency>

	<dependency>
		<groupId>org.springframeworkgroupId>
		<artifactId>spring-webmvcartifactId>
		<version>${spring.version}version>
	dependency>

	<dependency>
		<groupId>org.springframeworkgroupId>
		<artifactId>spring-context-supportartifactId>
		<version>${spring.version}version>
	dependency>

	<dependency>
		<groupId>org.springframeworkgroupId>
		<artifactId>spring-testartifactId>
		<version>${spring.version}version>
	dependency>

	<dependency>
		<groupId>org.springframeworkgroupId>
		<artifactId>spring-jdbcartifactId>
		<version>${spring.version}version>
	dependency>

	<dependency>
		<groupId>org.springframework.securitygroupId>
		<artifactId>spring-security-webartifactId>
		<version>4.1.0.RELEASEversion>
	dependency>

	<dependency>
		<groupId>org.springframework.securitygroupId>
		<artifactId>spring-security-configartifactId>
		<version>4.1.0.RELEASEversion>
	dependency>

	<dependency>
		<groupId>javax.servletgroupId>
		<artifactId>servlet-apiartifactId>
		<version>2.5version>
		<scope>providedscope>
	dependency>

dependencies>
<build>
	<plugins>
		
		<plugin>
			<groupId>org.apache.maven.pluginsgroupId>
			<artifactId>maven-compiler-pluginartifactId>
			<version>3.2version>
			<configuration>
				<source>1.7source>
				<target>1.7target>
				<encoding>UTF-8encoding>
			configuration>
		plugin>
		<plugin>
			<groupId>org.apache.tomcat.mavengroupId>
			<artifactId>tomcat7-maven-pluginartifactId>
			<configuration>
				
				<port>9090port>
				
				<path>/path>
			configuration>
		plugin>
	plugins>
build>

注意:如果只是给自己的项目中嵌入Spring Security安全框架,只需要添加如下两个jar包即可。

<dependency>
	<groupId>org.springframework.securitygroupId>
	<artifactId>spring-security-webartifactId>
	<version>4.1.0.RELEASEversion>
dependency>

<dependency>
	<groupId>org.springframework.securitygroupId>
	<artifactId>spring-security-configartifactId>
	<version>4.1.0.RELEASEversion>
dependency>

【3】创建web.xml文件(通过Spring Security拦截需要处理的请求和引入Spring Security的配置文件)。


<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xmlns="http://java.sun.com/xml/ns/javaee"
	xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
	version="2.5">	
	
  	 <context-param>
		<param-name>contextConfigLocationparam-name>
		<param-value>classpath:spring-security.xmlparam-value>
	 context-param>
	 <listener>
		<listener-class>
			org.springframework.web.context.ContextLoaderListener
		listener-class>
	 listener>
	
	
	 <filter>  
		<filter-name>springSecurityFilterChainfilter-name>  
		<filter-class>org.springframework.web.filter.DelegatingFilterProxyfilter-class>  
	 filter>  
	 <filter-mapping>  
		<filter-name>springSecurityFilterChainfilter-name>  
		<url-pattern>/*url-pattern>  
	 filter-mapping>
web-app>

【4】创建Spring Security配置文件:spring-security.xml(与 web.xml中引入的配置文件对应),代码中有配置的详细说明注解。



<beans:beans
	xmlns="http://www.springframework.org/schema/security"
	xmlns:beans="http://www.springframework.org/schema/beans"
	xmlns:dubbo="http://code.alibabatech.com/schema/dubbo"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
						http://code.alibabatech.com/schema/dubbo http://code.alibabatech.com/schema/dubbo/dubbo.xsd
						http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security.xsd">
 
	
	<http pattern="/*.html" security="none">http>
	<http pattern="/css/**" security="none">http>
	<http pattern="/img/**" security="none">http>
	<http pattern="/js/**" security="none">http>
	<http pattern="/plugins/**" security="none">http>
	
	<http pattern="/seller/add.do" security="none">http>
	
	
	<http use-expressions="false">
	    
		<intercept-url pattern="/**" access="ROLE_SELLER" />
		
		<form-login login-page="/login.html"
			default-target-url="/index.html"
			authentication-failure-url="/login_error.html"
			always-use-default-target="true" />
		
		<csrf disabled="true" />
		
		<headers>
			<frame-options policy="SAMEORIGIN" />
		headers>
		
		<logout />
	http>
	
	
	<authentication-manager>
	    
	  
	    	<authentication-provider>
		  		<user-service>
		  			<user name="admin" password="123456" authorities="ROLE_USER"/>
		  		user-service>
		  	authentication-provider>
	   
		
	authentication-manager>
	
 
 
	
	
beans:beans>

【5】需要自己创建:login.html(登录页面 如下)、index.html(登录成功跳转页面)、login_error.html(登录失败跳转页面)

DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>登陆title>
head>
<body>
    --欢迎登陆我的系统--
    <form action="/login" method="post">
	  用户名:<input name="username"><br>
	  密码:<input name="password"><br>
	  <button>登陆button>
    form>
body>
html>

三、项目实战中,后台业务逻辑实现重要代码摘取,供实战中使用

【1】配置文件中配置的,登录时用户名和密码的业务逻辑处理类(实现UserDetailsService:框架自带的接口),注意:普通demo不需要此部分,主要用于真是环境登录逻辑的处理。

public class UserDetailServiceImpl implements UserDetailsService {
	//当通过配置文件的形式,引入服务类时需要设置set方法。
	private SellerService sellerService;
	
	public void setSellerService(SellerService sellerService) {
		this.sellerService = sellerService;
	}
	
	@Override
	public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
		//GrantedAuthority : 定义用户角色,需要实现的接口
		List<GrantedAuthority> list =new ArrayList<>();
		//用户添加角色,SimpleGrantedAuthority可以定义用户角色,实现了GrantedAuthority接口,
                //格式必须以(ROLE_)开头
		list.add(new SimpleGrantedAuthority("ROLE_SELLER"));
		//从数据库中获取用户信息。
		TbSeller seller = sellerService.findOne(username);
		if(seller != null) {
			//返回username:传过来的参数。seller.getPassword:数据库中获取到的用户密码。
                        //list:用户的所有角色,可以从数据库中获取
			return new User(username, seller.getPassword(), list);
		}else {
			return null;
		}
	}
}

【2】BCrypt加密过程(配置中说明了BCryptMD5的区别)。

@RequestMapping("/add")
public Result add(@RequestBody TbSeller seller){
	try {
		//BCrypt加密使用的对象BCryptPasswordEncoder
		BCryptPasswordEncoder cryptPasswordEncoder = new BCryptPasswordEncoder();
		//使用encode方法对传入的密码加密,返回30位的字符串
		String encode = cryptPasswordEncoder.encode(seller.getPassword());
		//业务处理:接入对象中
		seller.setPassword(encode);
		//调用服务层,入库
		sellerService.add(seller);
		return new Result(true, "增加成功");
	} catch (Exception e) {
		e.printStackTrace();
		return new Result(false, "增加失败");
	}
}

四、当程序中需要用户名时,可通过 SecurityContextHolder 对象获取

SecurityContextHolder用于存储安全上下文security context的信息。当前操作的用户是谁,该用户是否已经被认证,他拥有哪些角色权限…这些都被保存在SecurityContextHolder中。SecurityContextHolder默认使用ThreadLocal策略来存储认证信息。看到ThreadLocal也就意味着,这是一种与线程绑定的策略。Spring Security在用户登录时自动绑定认证信息到当前线程,在用户退出时,自动清除当前线程的认证信息。但这一切的前提,是你在web场景下使用Spring Security

☏ 因为身份信息是与线程绑定的,所以可以在程序的任何地方使用静态方法获取用户信息。一个典型的获取当前登录用户的姓名的例子如下所示:getAuthentication() 返回了认证信息。

@RequestMapping("/name")
public Map<String, String> getName(){
	//获取登录名
	String name = SecurityContextHolder.getContext().getAuthentication().getName();
	Map<String, String> map = new HashMap<>();
	map.put("loginName", name);
	return map;
}

Authentication源码:

package org.springframework.security.core;// <1>
public interface Authentication extends Principal, Serializable { // <1>
    Collection<? extends GrantedAuthority> getAuthorities(); // <2>
    Object getCredentials();// <2>
    Object getDetails();// <2>
    Object getPrincipal();// <2>
    boolean isAuthenticated();// <2>
    void setAuthenticated(boolean var1) throws IllegalArgumentException;
}

【1】AuthenticationSpring Security包中的接口,直接继承自Principal类,而Principal是位于java.security包中的。可以见得,AuthenticationSpring Security中是最高级别的身份/认证的抽象。
【2】由这个顶级接口,我们可以得到用户拥有的权限信息列表,密码,用户细节信息,用户身份信息,认证信息。
authentication.getPrincipal()返回了一个 Object,我们将Principal强转成了Spring Security中最常用的UserDetails,这在Spring Security 中非常常见,接口返回Object,使用instanceof判断类型,强转成对应的具体实现类。接口详细解读如下:
 ● getAuthorities():权限信息列表,默认是GrantedAuthority接口的一些实现类,通常是代表权限信息的一系列字符串。
 ● getCredentials():密码信息,用户输入的密码字符串,在认证过后通常会被移除,用于保障安全。
 ● getDetails():细节信息,web应用中的实现接口通常为WebAuthenticationDetails,它记录了访问者的ip地址和sessionId的值。
 ● getPrincipal():最重要的身份信息,大部分情况下返回的是UserDetails接口的实现类,也是框架中的常用接口之一。

你可能感兴趣的:(SpringBoot,spring,spring,boot,后端,java,性能优化,web安全,面试)