实战Spring Security技术栈开发企业级认证与授权

系统架构

在这里插入图片描述

什么是Spring IO Platform

Spring IO Platform,简单的可以认为是一个依赖维护平台,该平台将相关依赖汇聚到一起,针对每个依赖,都提供了一个版本号;

这些版本对应的依赖都是经过测试的,可以保证一起正常使用。

为什么要使用Spring IO Platform

主要是解决依赖版本冲突问题,例如在使用Spring的时候,经常会使用到第三方库,一般大家都是根据经验挑选一个版本号或挑选最新的,随意性较大,其实这是有问题的,除非做过完整的测试,保证集成该版本的依赖不会出现问题,且后续集成其它第三方库的时候也不会出现问题,否则风险较大,且后续扩展会越来越困难,因为随着业务复杂度的增加,集成的第三方组件会越来会多,依赖之间的关联也会也来越复杂。

好消息是,Spring IO Platform能很好地解决这些问题,我们在添加第三方依赖的时候,不需要写版本号,它能够自动帮我们挑选一个最优的版本,保证最大限度的扩展,而且该版本的依赖是经过测试的,可以完美的与其它组件结合使用。

Spring IO Platform pom

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>
	<groupId>com.imooc.security</groupId>
	<artifactId>imooc-security</artifactId>
	<version>1.0.0-SNAPSHOT</version>
	<packaging>pom</packaging>

	<properties>
		<imooc.security.version>1.0.0-SNAPSHOT</imooc.security.version>
	</properties>
#有这两个依赖就可以将项目的依赖管理起来了start
	<dependencyManagement>
		<dependencies>
			<dependency>
				<groupId>io.spring.platform</groupId>
				<artifactId>platform-bom</artifactId>
				<version>Brussels-SR4</version>
				<type>pom</type>
				<scope>import</scope>
			</dependency>
			<dependency>
				<groupId>org.springframework.cloud</groupId>
				<artifactId>spring-cloud-dependencies</artifactId>
				<version>Dalston.SR2</version>
				<type>pom</type>
				<scope>import</scope>
			</dependency>
		</dependencies>
	</dependencyManagement>
#有这两个依赖就可以将项目的依赖管理起来了end
#配置maven的编译信息start
	<build>
		<plugins>
			<plugin>
				<groupId>org.apache.maven.plugins</groupId>
				<artifactId>maven-compiler-plugin</artifactId>
				<version>2.3.2</version>
				<configuration>
					<source>1.8</source>
					<target>1.8</target>
					<encoding>UTF-8</encoding>
				</configuration>
			</plugin>
		</plugins>
	</build>
	#配置maven的编译信息end
	<modules>
		<module>../imooc-security-app</module>
		<module>../imooc-security-browser</module>
		<module>../imooc-security-core</module>
		<module>../imooc-security-demo</module>
		<module>../imooc-security-authorize</module>
	</modules>
</project>

一个模块引入另外一个模块的依赖

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>
	<artifactId>imooc-security-app</artifactId>
	<parent>
		<groupId>com.imooc.security</groupId>
		<artifactId>imooc-security</artifactId>
		<version>1.0.0-SNAPSHOT</version>
		<relativePath>../imooc-security</relativePath>
	</parent>
	#这边引入了com.imooc.security模块的全部依赖,需在父类中加入版本说明
	<dependencies>
		<dependency>
			<groupId>com.imooc.security</groupId>
			<artifactId>imooc-security-core</artifactId>
			<version>${imooc.security.version}</version>
		</dependency>
	</dependencies>
</project>

打包一个可执行web服务的jar包?加一个编译插件

在打包成web服务模块的.pom文件中加入插件

<build>
	<plugins>
		<plugin>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-maven-plugin</artifactId>
			<version>1.5.6.RELEASE</version>
			<executions>
				<execution>
					<goals>
						<goal>repackage</goal>
					</goals>
				</execution>
			</executions>
		</plugin>
	</plugins>
	<finalName>demo</finalName>
</build>

restful Api与常规的Api的区别

1.常规的使用json来定义请求的成功或者失败
2.restful Api使用http的状态码来确定请求的成功或者失败

restful Api的描述

在这里插入图片描述

Spring的测试框架、测试用例的使用

1.模块中加入pom依赖

      <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-test</artifactId>
        <version>1.5.6.RELEASE</version>
      </dependency>

2.在模块中添加测试用例

package com.imooc.web.controller;

import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.http.MediaType;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
import org.junit.Before;
import org.junit.Test;
import org.springframework.boot.test.context.SpringBootTest;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;

@RunWith(SpringRunner.class) //表示如何来运行这个测试用例,我们用SpringRunner来运行
@SpringBootTest //表示这个类是一个springBoot的测试用例
public class UserControllerTest {

	//因为我们要测的是一个web程序,所以我们要伪造一个Mvc的环境,伪造的
	// 环境不会真正的启动我们的tomcat,所以测试用例执行的时候会很快
	@Autowired
	private WebApplicationContext wac;
	
	private MockMvc mockMvc;//伪造mvc的环境
	
	@Before //会在测试用例执行之前执行
	public void setup(){
		mockMvc = MockMvcBuilders.webAppContextSetup(wac).build();//伪造一个mvc环境
	}
	
	//开始写一个测试用例
	@Test
	public void whenQuerySuccess() throws Exception {
		String result = mockMvc.perform(get("/user").param("username", "jojo").param("age", "18").param("ageTo", "60").param("xxx", "yyy")
						// .param("size", "15")
						// .param("page", "3")
						// .param("sort", "age,desc")
						.contentType(MediaType.APPLICATION_JSON_UTF8))
				.andExpect(status().isOk()).andExpect(jsonPath("$.length()").value(3))
				.andReturn().getResponse().getContentAsString();
		
		System.out.println(result);
	}
	
}

idea导入eclipse的maven项目

在这里插入图片描述

idea运行单个测试用例及运行所有测试用例的方法

1.双击单个方法,run as
2.在文件上 run as

Spring的一些用法

1.@PathVariable将路径上的参数作为方法参数导入
2.@GetMapping("/{id:\d+}") ///使用正则表达式表示接受数字类型的参数

@JsonView的使用

在这里插入图片描述
1-2
在这里插入图片描述
3.在controller中指定视图
在这里插入图片描述

********************** 1.RESTful Api *****************************

在这里插入图片描述
1.RequestBody映射请求体到javaj方法的参数///
2.日期类型参数的处理
///通过传递时间戳到前端,让前台来决定展示格式
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
3.valid注解和BindingResult验证请求参数的合法性并处理验证结果
1)添加@valid的
在这里插入图片描述
2)添加需要验证的字段
在这里插入图片描述
3)BindingResult让验证可以进入函数体
///比如在校验参数没过时,需要记录日志
在这里插入图片描述

************************************************************

在这里插入图片描述
4)常用的验证注解
在这里插入图片描述
在这里插入图片描述

获取错误的字段和信息

在这里插入图片描述
5)自定义验证消息
在这里插入图片描述
6)自定义验证注解
1.自定义验证注解
在这里插入图片描述

2.验证逻辑
在这里插入图片描述
3.调用验证器
在这里插入图片描述

RESTful Api错误处理机制

在这里插入图片描述
1)Spring Boot 中默认的错误处理机制

2)如何自定义异常处理
定义浏览器的错误请求页面
在这里插入图片描述
自定义运行时异常
1)异常类处理

package com.imooc.exception;

public class UserNotExistException extends RuntimeException {
    private static final long serialVersionUID = -6112780192479692859L;

    private String id;

    public UserNotExistException(String id) {
        super("user not exist");
        this.id = id;
    }

    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }
}

2)调用抛出异常

throw new UserNotExistException (String id);

3)添加自己的异常信息(将id信息返回到异常信息)

package com.imooc.web.controller;


import com.imooc.exception.UserNotExistException;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.ResponseStatus;

import java.util.HashMap;
import java.util.Map;

@ControllerAdvice //代表这个类的方法都是处理其他Controller控制器所抛出的异常的 =>不处理请求,值处理controller请求
public class ControllerExceptionHandler {
    @ExceptionHandler(UserNotExistException.class) //任何一个方法抛出一个UserNotExistException异常是,都会执行下面的方法
    @ResponseBody //返回json
    @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
    public Map<String, Object> handleUserNotExistException(UserNotExistException ex) { //拿到抛出的异常
        Map<String, Object> result = new HashMap<>();
        result.put("id", ex.getId());
        result.put("message", ex.getMessage());
        return result;
    }
}

RESTful Api拦截器

在这里插入图片描述
1)过滤器

/**
 * 
 */
package com.imooc.web.filter;

import java.io.IOException;
import java.util.Date;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;

/**
 * @author zhailiang
 *
 */
//@Component  //要让过滤器起作用,申明成一个spring的Component,所有的流程都会经过这个过滤器
public class TimeFilter implements Filter {

	/* (non-Javadoc)
	 * @see javax.servlet.Filter#destroy()
	 */
	@Override
	public void destroy() {
		//销毁
		System.out.println("time filter destroy");
	}

	/* (non-Javadoc)
	 * @see javax.servlet.Filter#doFilter(javax.servlet.ServletRequest, javax.servlet.ServletResponse, javax.servlet.FilterChain)
	 */
	@Override
	public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
			throws IOException, ServletException {
		//执行
		System.out.println("time filter start");
		long start = new Date().getTime();
		chain.doFilter(request, response);
		System.out.println("time filter 耗时:"+ (new Date().getTime() - start));
		System.out.println("time filter finish");
	}

	/* (non-Javadoc)
	 * @see javax.servlet.Filter#init(javax.servlet.FilterConfig)
	 */
	@Override
	public void init(FilterConfig arg0) throws ServletException {
		//初始化
		System.out.println("time filter init");
	}

}

如何把一个普通(第三方的过滤器)类加到项目过滤器链中
/**
 * 
 */
package com.imooc.web.config;

import java.util.ArrayList;
import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;

import com.imooc.web.filter.TimeFilter;
import com.imooc.web.interceptor.TimeInterceptor;

/**
 * @author zhailiang
 *
 */
@Configuration  //**告诉spring这个类是一个配置类
public class WebConfig extends WebMvcConfigurerAdapter {
	
	@SuppressWarnings("unused")
	@Autowired
	private TimeInterceptor timeInterceptor;
	
	@Override
	public void addInterceptors(InterceptorRegistry registry) {
//		registry.addInterceptor(timeInterceptor);
	}
	
//	@Bean //**注册一个FilterRegistrationBean的bean
	public FilterRegistrationBean timeFilter() {
		
		FilterRegistrationBean registrationBean = new FilterRegistrationBean();
		
		TimeFilter timeFilter = new TimeFilter();
		registrationBean.setFilter(timeFilter);//**设置过滤器
		
		List<String> urls = new ArrayList<>();
		urls.add("/*");//**配置过滤器的URL
		registrationBean.setUrlPatterns(urls);
		
		return registrationBean;
		
	}

}

2)拦截器
//过滤器不知道请求的处理函数?
1.申明拦截器

/**
 * 
 */
package com.imooc.web.interceptor;

import java.util.Date;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.stereotype.Component;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

/**
 * @author zhailiang
 *
 */
@Component
public class TimeInterceptor implements HandlerInterceptor {

	/* (non-Javadoc)
	 * @see org.springframework.web.servlet.HandlerInterceptor#preHandle(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse, java.lang.Object)
	 */
	@Override
	public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
			throws Exception {
		System.out.println("preHandle");
		
		System.out.println(((HandlerMethod)handler).getBean().getClass().getName());
		System.out.println(((HandlerMethod)handler).getMethod().getName());
		
		request.setAttribute("startTime", new Date().getTime());
		return true;
	}

	/* (non-Javadoc)
	 * @see org.springframework.web.servlet.HandlerInterceptor#postHandle(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse, java.lang.Object, org.springframework.web.servlet.ModelAndView)
	 */
	@Override
	public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
			ModelAndView modelAndView) throws Exception {
		System.out.println("postHandle");
		Long start = (Long) request.getAttribute("startTime");
		System.out.println("time interceptor 耗时:"+ (new Date().getTime() - start));

	}

	/* (non-Javadoc)
	 * @see org.springframework.web.servlet.HandlerInterceptor#afterCompletion(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse, java.lang.Object, java.lang.Exception)
	 */
	@Override
	public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
			throws Exception {
		System.out.println("afterCompletion");
		Long start = (Long) request.getAttribute("startTime");
		System.out.println("time interceptor 耗时:"+ (new Date().getTime() - start));
		System.out.println("ex is "+ex);

	}

}

2.注册拦截器
在这里插入图片描述
3)切片

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
课程介绍 【完善体系+精品资料】本课程总计115课时,打造全网最全的微服务体系课程;从微服务是什么、能够做什么开始讲起,绝对零基础入门到精通类型。课程整体脉络十分清晰,每个章节一个知识点,画图+源码+运行讲解,不信你学不会。1、课程先讲解了什么是单体架构、什么是微服务架构、他们之间有什么区别和联系,各自有什么优缺点。2、从本质入手,使用最简单的Spring Boot搭建微服务,让你认清微服务是一种思想和解决问题的手段,而不是新兴技术。3、讲解Spring Boot 与 Spring Cloud 微服务架构之间的联系,原生的RestTemplate工具,以及Actuator监控端点的使用。4、带着微服务所带来的各种优缺点,为大家引入服务发现与注册的概念和原理,从而引入我们的第一个注册中心服务Eureka。5、引入负载均衡的理念,区分什么是服务端负载均衡,什么是客户端负载均衡,进而引入Ribbon负载均衡组件的详细使用。6、为了解决微服务之间复杂的调用,降低代码的复杂度,我们引入了Feign声明式客户端,让你几行代码学习服务的远程调用。7、为了解决服务之间的稳定性,避免发生雪崩问题,我们引入了Hystrix断路器,服务降级和熔断机制。8、微服务集群十分庞大,监控起来是十分困难的,尤其是对每一个接口的熔断情况进行监控,因此我们引入了Turbine微服务监控。9、微服务的调用是杂乱无章的,可以网状调用,怎么做到统一的入口出口,统一的授权、加密、解密、日志过滤,我们引入了第一代网关Zuul。10、微服务的配置分散,每次要修改配置都要重启服务,因此我们引入了Config配置中心。11、跟上主流,Consul是当前主流的服务注册与发现、配置中心一体化的解决方案。12、阿里的Nacos服务注册与发现、配置中心在国内炙手可热,Nacos 经历过双十一的微服务中间件。13、Turbin做微服务监控还是太弱,我们需要更强大,可视化,操作性更强的监控系统,因此我引入了Spring Boot Admin体系。14、Zuul已经停止更新支持,Spring Cloud官方推荐的二代网关Spring Cloud Gateway更加强大。15、微服务的安全架构体系虽然复杂,但是是有学习条例的,什么是认证授权、什么是OAuth2.0的原理、 JWT、怎么样去开发实现。 课程资料 【独家资料】1、课程附带全部63个项目源码,其中Hoxton版本项目源码37个,Edgware版本项目26个,2、230页高清PDF正版课件。3、附带nacos、consul、cmder等视频配套软件。学习方法1、每一节课程均有代码,较好的方式为一边听我的讲解,一边使用我提供的项目代码进行观察和运行。2、课程体系庞大,但是并不杂乱,每个章节只针对一个知识点,减轻学习压力。3、坚持每天学习1~2个章节,可以在地铁、公交上用手机学习。【完善知识体系图】

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

混沌人生

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值