有状态 vs 无状态

有状态

那么Session在何时创建呢?
当然还是在服务器端程序运行的过程中创建的,不同语言实现的应用程序有不同创建Session的方法,而在Java中是通过调用HttpServletRequest的getSession方法(使用true作为参数)创建的。
在创建了Session的同时,服务器会为该Session生成唯一的Session id,而这个Session id在随后的请求中会被用来重新获得已经创建的Session;
在Session被创建之后,就可以调用Session相关的方法往Session中增加内容了,而这些内容只会保存在服务器中,发到客户端的只有Session id;
当客户端再次发送请求的时候,会将这个Session id带上,服务器接受到请求之后就会依据Session id找到相应的Session,从而再次使用之。

无状态

有状态 vs 无状态

微服务认证方案

  • 微服务认证方案01-处处安全
  • 微服务认证方案02-外部无状态,内部有状态
  • 微服务认证方案03-网关认证授权,内部裸奔
  • 微服务认证方案04-内部裸奔改进

微服务认证方案01-处处安全

OAuth2实现单点登录SSO

https://github.com/chengjiansheng/cjs-oauth2-sso-demo.git

微服务认证方案02-外部无状态,内部有状态

微服务认证方案03-网关认证授权,内部裸奔

微服务认证方案04-内部裸奔改进

方案对比与选择

访问控制模型

JWT是什么?

JWT操作工具类分享

小程序登录逻辑

实现登录状态检查

public @interface CheckLogin {
}
import com.itmuch.usercenter.util.JwtOperator;
import io.jsonwebtoken.Claims;
import lombok.RequiredArgsConstructor;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes; import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;
import java.util.Objects; @Aspect
@Component
@RequiredArgsConstructor(onConstructor = @__(@Autowired))
public class AuthAspect {
private final JwtOperator jwtOperator; @Around("@annotation(com.itmuch.usercenter.auth.CheckLogin)")
public Object checkLogin(ProceedingJoinPoint point) throws Throwable {
checkToken();
return point.proceed();
} private void checkToken() {
try {
// 1. 从header里面获取token
HttpServletRequest request = getHttpServletRequest(); String token = request.getHeader("X-Token"); // 2. 校验token是否合法&是否过期;如果不合法或已过期直接抛异常;如果合法放行
Boolean isValid = jwtOperator.validateToken(token);
if (!isValid) {
throw new SecurityException("Token不合法!");
} // 3. 如果校验成功,那么就将用户的信息设置到request的attribute里面
Claims claims = jwtOperator.getClaimsFromToken(token);
request.setAttribute("id", claims.get("id"));
request.setAttribute("wxNickname", claims.get("wxNickname"));
request.setAttribute("role", claims.get("role"));
} catch (Throwable throwable) {
throw new SecurityException("Token不合法");
}
} private HttpServletRequest getHttpServletRequest() {
RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();
ServletRequestAttributes attributes = (ServletRequestAttributes) requestAttributes;
return attributes.getRequest();
} @Around("@annotation(com.itmuch.usercenter.auth.CheckAuthorization)")
public Object checkAuthorization(ProceedingJoinPoint point) throws Throwable {
try {
// 1. 验证token是否合法;
this.checkToken();
// 2. 验证用户角色是否匹配
HttpServletRequest request = getHttpServletRequest();
String role = (String) request.getAttribute("role"); MethodSignature signature = (MethodSignature) point.getSignature();
Method method = signature.getMethod();
CheckAuthorization annotation = method.getAnnotation(CheckAuthorization.class); String value = annotation.value(); if (!Objects.equals(role, value)) {
throw new SecurityException("用户无权访问!");
}
} catch (Throwable throwable) {
throw new SecurityException("用户无权访问!", throwable);
}
return point.proceed();
}
}
@GetMapping("/{id}")
@CheckLogin
public User findById(@PathVariable Integer id) {
log.info("我被请求了...");
return this.userService.findById(id);
}

Feign调用时传递token

使用拦截器

import feign.RequestInterceptor;
import feign.RequestTemplate;
import org.apache.commons.lang3.StringUtils;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes; import javax.servlet.http.HttpServletRequest; public class TokenRelayRequestIntecepor implements RequestInterceptor {
@Override
public void apply(RequestTemplate template) {
// 1. 获取到token
RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();
ServletRequestAttributes attributes = (ServletRequestAttributes) requestAttributes;
HttpServletRequest request = attributes.getRequest();
String token = request.getHeader("X-Token"); // 2. 将token传递
if (StringUtils.isNotBlank(token)) {
template.header("X-Token", token);
} }
}

RestTemplate传递token

RequestInterceptor
import feign.RequestInterceptor;
import feign.RequestTemplate;
import org.apache.commons.lang3.StringUtils;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes; import javax.servlet.http.HttpServletRequest; public class TokenRelayRequestIntecepor implements RequestInterceptor {
@Override
public void apply(RequestTemplate template) {
// 1. 获取到token
RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();
ServletRequestAttributes attributes = (ServletRequestAttributes) requestAttributes;
HttpServletRequest request = attributes.getRequest();
String token = request.getHeader("X-Token"); // 2. 将token传递
if (StringUtils.isNotBlank(token)) {
template.header("X-Token", token);
} }
}
ClientHttpRequestInterceptor
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpRequest;
import org.springframework.http.client.ClientHttpRequestExecution;
import org.springframework.http.client.ClientHttpRequestInterceptor;
import org.springframework.http.client.ClientHttpResponse;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes; import javax.servlet.http.HttpServletRequest;
import java.io.IOException; public class TestRestTemplateTokenRelayInterceptor implements ClientHttpRequestInterceptor {
@Override
public ClientHttpResponse intercept(HttpRequest request, byte[] body, ClientHttpRequestExecution execution) throws IOException {
RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();
ServletRequestAttributes attributes = (ServletRequestAttributes) requestAttributes;
HttpServletRequest httpRequest = attributes.getRequest();
String token = httpRequest.getHeader("X-Token"); HttpHeaders headers = request.getHeaders();
headers.add("X-Token", token); // 保证请求继续执行
return execution.execute(request, body);
}
}

实现用户权限验证

@Retention(RetentionPolicy.RUNTIME)
public @interface CheckAuthorization {
String value();
}

import com.itmuch.usercenter.util.JwtOperator;
import io.jsonwebtoken.Claims;
import lombok.RequiredArgsConstructor;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes; import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;
import java.util.Objects; @Aspect
@Component
@RequiredArgsConstructor(onConstructor = @__(@Autowired))
public class AuthAspect {
private final JwtOperator jwtOperator; @Around("@annotation(com.itmuch.usercenter.auth.CheckLogin)")
public Object checkLogin(ProceedingJoinPoint point) throws Throwable {
checkToken();
return point.proceed();
} private void checkToken() {
try {
// 1. 从header里面获取token
HttpServletRequest request = getHttpServletRequest(); String token = request.getHeader("X-Token"); // 2. 校验token是否合法&是否过期;如果不合法或已过期直接抛异常;如果合法放行
Boolean isValid = jwtOperator.validateToken(token);
if (!isValid) {
throw new SecurityException("Token不合法!");
} // 3. 如果校验成功,那么就将用户的信息设置到request的attribute里面
Claims claims = jwtOperator.getClaimsFromToken(token);
request.setAttribute("id", claims.get("id"));
request.setAttribute("wxNickname", claims.get("wxNickname"));
request.setAttribute("role", claims.get("role"));
} catch (Throwable throwable) {
throw new SecurityException("Token不合法");
}
} private HttpServletRequest getHttpServletRequest() {
RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();
ServletRequestAttributes attributes = (ServletRequestAttributes) requestAttributes;
return attributes.getRequest();
} @Around("@annotation(com.itmuch.usercenter.auth.CheckAuthorization)")
public Object checkAuthorization(ProceedingJoinPoint point) throws Throwable {
try {
// 1. 验证token是否合法;
this.checkToken();
// 2. 验证用户角色是否匹配
HttpServletRequest request = getHttpServletRequest();
String role = (String) request.getAttribute("role"); MethodSignature signature = (MethodSignature) point.getSignature();
Method method = signature.getMethod();
CheckAuthorization annotation = method.getAnnotation(CheckAuthorization.class); String value = annotation.value(); if (!Objects.equals(role, value)) {
throw new SecurityException("用户无权访问!");
}
} catch (Throwable throwable) {
throw new SecurityException("用户无权访问!", throwable);
}
return point.proceed();
}
}
@PutMapping("/audit/{id}")
@CheckAuthorization("admin")
public Share auditById(@PathVariable Integer id, @RequestBody ShareAuditDTO auditDTO) {
return this.shareService.auditById(id, auditDTO);
}

本章总结

7.【Spring Cloud Alibaba】微服务的用户认证与授权的更多相关文章

  1. Spring Cloud Alibaba | 微服务分布式事务之Seata

    Spring Cloud Alibaba | 微服务分布式事务之Seata 本篇实战所使用Spring有关版本: SpringBoot:2.1.7.RELEASE Spring Cloud:Green ...

  2. Spring Cloud Alibaba微服务一站式解决方案-开篇v2.2.1.RELEASE

    学习路线 **本人博客网站 **IT小神 www.itxiaoshen.com 生态概述 架构演进 什么是微服务 https://martinfowler.com/microservices/ Mic ...

  3. Spring Cloud Alibaba微服务架构入门最容易理解篇

    微服务架构介绍 Spring Cloud Alibaba推荐的微服务生态架构基于分层架构实现如下: 接入层:最外层为LVS+Keepalived,可承受几十万级高并发流量洪峰,然后再通过内层的ngin ...

  4. Spring Cloud Alibaba微服务生态的基础实践

    目录 一.背景 二.初识Spring Cloud Alibaba 三.Nacos的基础实践 3.1 安装Nacos并启动服务 3.2 建立微服务并向Nacos注册服务 3.3 建立微服务消费者进行服务 ...

  5. Spring Cloud构建微服务架构:服务网关(路由配置)【Dalston版】

    转载:http://blog.didispace.com/spring-cloud-starter-dalston-6-2/ 原创  2017-08-26  翟永超  Spring Cloud 被围观 ...

  6. 【微服务】使用spring cloud搭建微服务框架,整理学习资料

    写在前面 使用spring cloud搭建微服务框架,是我最近最主要的工作之一,一开始我使用bubbo加zookeeper制作了一个基于dubbo的微服务框架,然后被架构师否了,架构师曰:此物过时.随 ...

  7. 干货|基于 Spring Cloud 的微服务落地

    转自 微服务架构模式的核心在于如何识别服务的边界,设计出合理的微服务.但如果要将微服务架构运用到生产项目上,并且能够发挥该架构模式的重要作用,则需要微服务框架的支持. 在Java生态圈,目前使用较多的 ...

  8. 基于Spring Cloud的微服务落地

    微服务架构模式的核心在于如何识别服务的边界,设计出合理的微服务.但如果要将微服务架构运用到生产项目上,并且能够发挥该架构模式的重要作用,则需要微服务框架的支持. 在Java生态圈,目前使用较多的微服务 ...

  9. Spring Cloud与微服务构建:Spring Cloud简介

    Spring Cloud简介 微服务因该具备的功能 微服务可以拆分为"微"和"服务"二字."微"即小的意思,那到底多小才算"微&q ...

随机推荐

  1. 【javaScript】获取某年某月的的最后一天(即当月天数) 妙用

    javaScript里 面的new Date("xxxx/xx/xx")这个日期的构造方法有一个妙处,当你传入的是"xxxx/xx/0"(0号)的话,得到的日期 ...

  2. 20191217HNOI 模拟赛 复活石

    题目描述: 分析: 我也不知道我在干sm,但就是没写出来2333 枚举 i 的每个质因子 j ,复杂度为n^(3/2) 为什么我会认为是n^2啊2333 然后考虑 f ( j )对g ( i )做了多 ...

  3. H5 + WebGL 展示的3D无人机

    前言 近年来,无人机的发展越发迅速,既可民用于航拍,又可军用于侦察,涉及行业广泛,也被称为“会飞的照相机”.但作为军事使用,无人机的各项性能要求更加严格.重要.本系统则是通过 Hightopo 的   ...

  4. java web 项目中基础技术

    1. 选择版本控制器(git, svn) 2. 用户登录的时候, 你需要进行认证, 权限受理 可以使用 spring shiro 框架,进行上面的工作 3. 过滤器(filter),监听器(liste ...

  5. 压力测试---Jemeter的使用

    一.线程组配置 线程组相当于有多个用户,同时去执行相同的一批次任务.每个线程之间都是隔离的,互不影响的.一个线程的执行过程中,操作的变量,不会影响其他线程的变量值. Delay Thread crea ...

  6. kdevelop 是什么 什么鬼(windows系统非linux)

    这个软件尼玛 有懂的没,编译执行 1.需要gcc 2.需要啥怎么配置尼玛 3........................... 4.疯了都 大家懂得来说说

  7. Spring-cloud微服务实战【七】:服务熔断与降级hystrix

      在之前的文章中,我们先后介绍了eureka,ribbon,feign,使用eureka集群的方式来保证注册中心的高可用,在eureka中使用ribbon进行负载均衡,使用feign接口替换手动编码 ...

  8. Redis搭建哨兵模式

    一 安装Redis 1. 从https://redis.io/download redis官网下载二进制包安装 例如:wget http://download.redis.io/releases/re ...

  9. Boyer-Moore 算法 Leetcode169

    Boyer-Moore 算法 Leetcode169 一.题目 169. 多数元素 给定一个大小为 n 的数组,找到其中的多数元素.多数元素是指在数组中出现次数大于 ⌊ n/2 ⌋ 的元素. 你可以假 ...

  10. 漏洞利用:验证绕过,XSS利用,Cookic盗用,文件上传

    1.      文件上传 低级别 写好上传的内容 选择好上传的文件 上传成功. 测试:访问文件,执行代码 中级别 修改文件后缀为png 上传该文件 抓包修改文件后缀为php,然后允许数据包通过. 上传 ...