十五.SpringCloud+Security+Oauth2实现微服务授权 -前端登录实战

简介: SpringCloud+Security+Oauth2实现微服务授权 -前端登录实战

1.前端登录

1.1.方案分析

后端没什么说的,跟之前文章中一样,你需要搭建独立的认证中心,其他的微服务做为资源服务即可,对于前台登录首先少不了账号密码登录模式,所以我们的方案可以这样,前台直接封装请求向认证中心获取Token可以使用“password”模式,然后把Token存储到SessionStorage中,请求资源的时候给Header添加上Token即可.

1.2.前端获取Token

使用“password”模式请求Token,如下:

var param = "username=zs&password=123&client_id=system&client_secret=123&grant_type=password";
//请求参数的内容格式为普通方式,否则默认使用JSON格式提交参数
var config={
   
    headers: {
   'Content-Type': 'application/x-www-form-urlencoded'}
};

this.$http.post("/auth/oauth/token",param,config).then(res=>{
   
    //获取到Token
    var token = res.data.access_token;
    var refresh_token = res.data.refresh_token;

    //把token存储起来
    sessionStorage.setItem("U-TOKEN",token);
    sessionStorage.setItem("R-TOKEN",refresh_token );
    sessionStorage.setItem("user",'{"username":"zs"}');
    //修改登录成功后跳转到首页
    this.$router.push({
    path: '/main' });
    this.logining = false;
    return;
}).catch(error => {
   
    this.$message.error(error.message);
    this.logining = false;
    return;
});

这里 Content-Type 设置为 application/x-www-form-urlencode ,发送请求到认证中心获取Token,然后存储Token

当然您可以会觉得这样去带参数会暴露 client_secret 秘钥,那你可以稍作修改,就是做一个登陆接口,前台只带着用户名和密码去登陆,在登录接口中获取client_id和client_secret 加上参数中的用户名和密码组装成完整的URL使用HTTP调用认证中心的令牌获取接口获取令牌,然后返回给客户端,比如:

     var loginParams = {
    username: "zs", password: "123",clientId:"system"};
            //发起请求 http://localhost:1020/hrm/auth/auth/oauth/token?
     this.$http.post("/auth/login/accessToken",loginParams).then(res=>{
   
         //获取到Token
         var token = res.data.resultObj.access_token;
         var refresh_token = res.data.resultObj.refresh_token;
         //把token存储起来
         sessionStorage.setItem("U-TOKEN",token);
         sessionStorage.setItem("R-TOKEN",refresh_token);
         sessionStorage.setItem("user",'{"username":"zs"}');
         //修改登录成功后跳转到首页
         this.$router.push({
    path: '/main' });
         this.logining = false;
         return;
     }).catch(error => {
   
         this.$message.error(error.message);
         this.logining = false;
         return;
     });

后台登录代码

 @Override
    public AjaxResult login(Login login) {
   

        ValidUtils.assertNotNull(login.getUsername(),"用户名不可为空");
        ValidUtils.assertNotNull(login.getPassword(),"密码不可为空");
        ValidUtils.assertNotNull(login.getClientId(),"clientId不可为空");

        //String urlAccessToken = "%s/oauth/token?username=%s&password=%S&client_id=%S&client_secret=%s&grant_type=password"
        //组装获取Token的Url
        String accessTokenUrl = String.format(AuthConstants.URL_ACCESS_TOKEN,
                oauthProperties.getAuthServerUrl(),    //获取令牌地址
                login.getUsername(),    //用户名
                login.getPassword(),    //密码
                login.getClientId(),    //客户端ID
                oauthProperties.getSecrectByClentId(login.getClientId()));    //秘钥

            //发送Http请求获取Token,返回给浏览器
              return  AjaxResult.me().setResultObj(HttpUtil.sendPost(accessTokenUrl));

1.3.请求头添加Token

使用Axios拦截器给请求头添加Token,如下:

axios.interceptors.request.use(config => {
   
    //如果已经登录了,每次都把token作为一个请求头传递过程
    if (sessionStorage.getItem('U-TOKEN')) {
   
        // 让每个请求携带token--['X-Token']为自定义key 请根据实际情况自行修改
        config.headers['Authorization'] = "Bearer "+sessionStorage.getItem('U-TOKEN')
    }
    return config
}, error => {
   
    // Do something with request error
    Promise.reject(error)
})

这样一来,每次发送请求都会在请求头中携带Token了,请求到了网关层就会对Token进行校验

2.Token无感刷新

2.1.方案分析

如果Token过期怎么办?Token过期请求会失败出现401错误,

  1. 解决方案一:可以通过Axios的后置拦截器拦截到401错误直接弹出窗口要求用户去登录,当然这种方式对用户体验不是很好。
  2. 方案二:可以在服务器端比如zuul中做授权失败的处理器,发现是401异常就自动向认证中心发送Token刷新请求,然后把新的Token写回客户端(比如通过cookie),接着重新转发失败的请求
  3. 方案三:可以在前端做文章,通通过Axios的后置拦截器拦截到401错误,然后同步发送刷新Token的请求重新得到Token,把Token重新存储到SessionStorage,然后重新转发失败的请求,请求头携带新的Token

后面两种都可以实现Token无感刷新,第三种方案更适合前后端分离项目

2.2.后置拦截器

Axios响应拦截器拦截401异常

axios.interceptors.response.use(config => {
   
    return config
},error => {
   
    if (error && error.response) {
   
        switch (error.response.status) {
   
            case 401: return doRequest(error);
        }
    }
    Promise.reject(error)
});

如果是401异常,说明Token过期了,同步发送刷新Token请求,刷新TokenURL是

/auth/oauth/token?client_id=system&client_secret=123
&grant_type=refresh_token&refresh_token=刷新Token

刷新Token是需要带着上一次获取Token返回的refresh_token值,所以在登录成功后除了要保持Token还要保存refresh_token

刷新Token请求如下:

async function doRequest (error) {
   
    try {
   
        //刷新Token请求
        const data = await getNewToken();
        var token = data.data.access_token;
        var refresh_token = data.data.refresh_token;
        //重新设置Token
        sessionStorage.setItem("U-TOKEN",token);
        sessionStorage.setItem("R-TOKEN",refresh_token);
        console.log("刷新Token:"+token);
        //继续请求之前未完成的请求
        const res = await axios.request(error.config);
        return res;
    } catch(err) {
   
        alert("登录失效,请重新登录");
        sessionStorage.clear();
        router.replace({
    path:"/login" });
        return err;
    }
}

async function getNewToken() {
   
    //获取到保存的refresh_token值
    var refreshToken = sessionStorage.getItem('R-TOKEN');
    //这里要发送同步请求
    return await axios({
   
        url: '/auth/oauth/token?client_id=system&client_secret=123&grant_type=refresh_token&refresh_token='+refreshToken,
        method: 'post',
        headers: {
   
            'Content-Type':'application/x-www-form-urlencoded'
        }
    })
}

同步方式获取到新的Token,重新存储到sessionStorage中,然后调用axios.request继续执行之前的请求,这一次请求头中带的就是新的Token

3.总结

到这里就结束了,这里介绍了两个内容,一个是使用“password”授权模式基于账号密码的登录,二个是基于前端的Token刷新,当然对于短信登录,邮件登录,三方登录肯定有所不一样,这里暂不讨论,希望文章对你有所帮助

相关文章
|
监控 Java API
Spring Boot 3.2 结合 Spring Cloud 微服务架构实操指南 现代分布式应用系统构建实战教程
Spring Boot 3.2 + Spring Cloud 2023.0 微服务架构实践摘要 本文基于Spring Boot 3.2.5和Spring Cloud 2023.0.1最新稳定版本,演示现代微服务架构的构建过程。主要内容包括: 技术栈选择:采用Spring Cloud Netflix Eureka 4.1.0作为服务注册中心,Resilience4j 2.1.0替代Hystrix实现熔断机制,配合OpenFeign和Gateway等组件。 核心实操步骤: 搭建Eureka注册中心服务 构建商品
1519 3
|
缓存 负载均衡 监控
微服务架构下的电商API接口设计:策略、方法与实战案例
本文探讨了微服务架构下的电商API接口设计,旨在打造高效、灵活与可扩展的电商系统。通过服务拆分(如商品、订单、支付等模块)和标准化设计(RESTful或GraphQL风格),确保接口一致性与易用性。同时,采用缓存策略、负载均衡及限流技术优化性能,并借助Prometheus等工具实现监控与日志管理。微服务架构的优势在于支持敏捷开发、高并发处理和独立部署,满足电商业务快速迭代需求。未来,电商API设计将向智能化与安全化方向发展。
619 102
|
10月前
|
Cloud Native Serverless API
微服务架构实战指南:从单体应用到云原生的蜕变之路
🌟蒋星熠Jaxonic,代码为舟的星际旅人。深耕微服务架构,擅以DDD拆分服务、构建高可用通信与治理体系。分享从单体到云原生的实战经验,探索技术演进的无限可能。
微服务架构实战指南:从单体应用到云原生的蜕变之路
|
NoSQL MongoDB 微服务
微服务——MongoDB实战演练——文章评论的基本增删改查
本节介绍了文章评论的基本增删改查功能实现。首先,在`cn.itcast.article.dao`包下创建数据访问接口`CommentRepository`,继承`MongoRepository`以支持MongoDB操作。接着,在`cn.itcast.article.service`包下创建业务逻辑类`CommentService`,通过注入`CommentRepository`实现保存、更新、删除及查询评论的功能。最后,新建Junit测试类`CommentServiceTest`,对保存和查询功能进行测试,并展示测试结果截图,验证功能的正确性。
341 2
|
NoSQL Java MongoDB
微服务——MongoDB实战演练——文章评论实体类的编写
本节主要介绍文章评论实体类的编写,创建了包`cn.itcast.article.po`用于存放实体类。具体实现中,`Comment`类通过`@Document`注解映射到MongoDB的`comment`集合,包含主键、内容、发布时间、用户ID、昵称等属性,并通过`@Indexed`和`@CompoundIndex`注解添加单字段及复合索引,以提升查询效率。同时提供了Mongo命令示例,便于理解和操作。
273 2
|
10月前
|
监控 Cloud Native Java
Spring Boot 3.x 微服务架构实战指南
🌟蒋星熠Jaxonic,技术宇宙中的星际旅人。深耕Spring Boot 3.x与微服务架构,探索云原生、性能优化与高可用系统设计。以代码为笔,在二进制星河中谱写极客诗篇。关注我,共赴技术星辰大海!(238字)
1428 2
Spring Boot 3.x 微服务架构实战指南
|
NoSQL 测试技术 MongoDB
微服务——MongoDB实战演练——MongoTemplate实现评论点赞
本节介绍如何使用MongoTemplate实现评论点赞功能。传统方法通过查询整个文档并更新所有字段,效率较低。为优化性能,采用MongoTemplate对特定字段直接操作。代码中展示了如何利用`Query`和`Update`对象构建更新逻辑,通过`update.inc("likenum")`实现点赞数递增。测试用例验证了功能的正确性,确保点赞数成功加1。
322 0
|
NoSQL 测试技术 MongoDB
微服务——MongoDB实战演练——根据上级ID查询文章评论的分页列表
本节介绍如何根据上级ID查询文章评论的分页列表,主要包括以下内容:(1)在CommentRepository中新增`findByParentid`方法,用于按父ID查询子评论分页列表;(2)在CommentService中新增`findCommentListPageByParentid`方法,封装分页逻辑;(3)提供JUnit测试用例,验证功能正确性;(4)使用Compass插入测试数据并执行测试,展示查询结果。通过这些步骤,实现对评论的高效分页查询。
280 0
|
12月前
|
负载均衡 监控 Java
微服务稳定性三板斧:熔断、限流与负载均衡全面解析(附 Hystrix-Go 实战代码)
在微服务架构中,高可用与稳定性至关重要。本文详解熔断、限流与负载均衡三大关键技术,结合API网关与Hystrix-Go实战,帮助构建健壮、弹性的微服务系统。
1032 1
微服务稳定性三板斧:熔断、限流与负载均衡全面解析(附 Hystrix-Go 实战代码)
|
NoSQL Java 微服务
2025 年最新 Java 面试从基础到微服务实战指南全解析
《Java面试实战指南:高并发与微服务架构解析》 本文针对Java开发者提供2025版面试技术要点,涵盖高并发电商系统设计、微服务架构实现及性能优化方案。核心内容包括:1)基于Spring Cloud和云原生技术的系统架构设计;2)JWT认证、Seata分布式事务等核心模块代码实现;3)数据库查询优化与高并发处理方案,响应时间从500ms优化至80ms;4)微服务调用可靠性保障方案。文章通过实战案例展现Java最新技术栈(Java 17/Spring Boot 3.2)的应用.
1073 9

热门文章

最新文章

  • 1
    前端如何存储数据:Cookie、LocalStorage 与 SessionStorage 全面解析
    1280
  • 2
    【CSS】前端三大件之一,如何学好?从基本用法开始吧!(九):强势分析Animation动画各类参数;从播放时间、播放方式、播放次数、播放方向、播放状态等多个方面,完全了解CSS3 Animation
    586
  • 3
    【CSS】前端三大件之一,如何学好?从基本用法开始吧!(八):学习transition过渡属性;本文学习property模拟、duration过渡时间指定、delay时间延迟 等多个参数
    445
  • 4
    【CSS】前端三大件之一,如何学好?从基本用法开始吧!(七):学习ransform属性;本文学习 rotate旋转、scale缩放、skew扭曲、tanslate移动、matrix矩阵 多个参数
    445
  • 5
    【CSS】前端三大件之一,如何学好?从基本用法开始吧!(六):全方面分析css的Flex布局,从纵、横两个坐标开始进行居中、两端等元素分布模式;刨析元素间隔、排序模式等
    568
  • 6
    【CSS】前端三大件之一,如何学好?从基本用法开始吧!(五):背景属性;float浮动和position定位;详细分析相对、绝对、固定三种定位方式;使用浮动并清除浮动副作用
    744
  • 7
    【CSS】前端三大件之一,如何学好?从基本用法开始吧!(四):元素盒子模型;详细分析边框属性、盒子外边距
    1454
  • 8
    【CSS】前端三大件之一,如何学好?从基本用法开始吧!(三):元素继承关系、层叠样式规则、字体属性、文本属性;针对字体和文本作样式修改
    321
  • 9
    【CSS】前端三大件之一,如何学好?从基本用法开始吧!(二):CSS伪类:UI伪类、结构化伪类;通过伪类获得子元素的第n个元素;创建一个伪元素展示在页面中;获得最后一个元素;处理聚焦元素的样式
    1177
  • 10
    【CSS】前端三大件之一,如何学好?从基本用法开始吧!(一):CSS发展史;CSS样式表的引入;CSS选择器使用,附带案例介绍
    518