Java SpringCloud 分布式鉴权 --Cookie携带token 作者:哇塞大嘴好帥(哇塞大嘴好帅)

Java SpringCloud 分布式鉴权 --Cookie携带token

​ 该鉴权思路为,前端登入账号如果账号密码正确后端返回前端jwt字符串,并且通过JavaScript讲返回的jwt保存到cookie里。以后每次通过网关进行访问都会经过网关拦截器判断是否登入、jwt是否过期。如果过期或者没有登入则跳转登入页面。

​ 这是我第一次发布博文,谢谢大家支持,如果我的文章不够详细,联系我的邮箱y51288033@outlook.com 我远程帮助你
下期更新:Java SpringCloud 分布式鉴权 --使用Shiro安全框架共享Session方法

JWT工具类

package com.dazuizui.api.utils;

import com.dazuizui.api.pojo.User;
import com.sun.javafx.scene.traversal.Algorithm;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.JwtBuilder;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;

import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;

/**
 * @author 哇塞大嘴好帅
 * @Time   2020/8/7 21:54
 * @Text   该工具类负责生成和解析JWT
 */
public class JwtUtil {
    /**
     * 生成或解析令牌时候所需要的密钥
     */
    private final static String JWTKey = "您的密钥";

    /**
     * 生成密文
     * @return
     */
    public static String createJWT(User user){
        //构建jwt令牌
        JwtBuilder builder = Jwts.builder();
        builder.setIssuer("颁发者"); //颁发者
        builder.setIssuedAt(new Date()); //颁发时间
        builder.setSubject("主题");   //主题
        builder.setExpiration(new Date(System.currentTimeMillis()+3600000));  //过期时间 设置3600秒

        //自定义信息 自定义载荷
        Map<String,Object> map = new HashMap<>();
        map.put("username","登入者昵称");
        builder.addClaims(map); //添加载荷

        builder.signWith(SignatureAlgorithm.HS256,JWTKey); //1.算法 2.密钥
        //生成密文
        String jstString = builder.compact();
        return jstString;
    }

    /**
     * 解析密钥
     * @param token 传入的token 并且从token解析的数据获取登入的用户名
     * @return
     */
    public static String analysisJWT(String token){
        System.out.println("获取到的"+token);
        Claims body = Jwts.parser()
                //密钥
                .setSigningKey(JWTKey)
                //要解析的令牌
                .parseClaimsJws(token)
                //获取解析后的数据
                .getBody();
        System.out.println(body.get("username"));
        return (String) body.get("username");
    }
}

网关编写 采用Gateway网关

<!--网关-->
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-gateway</artifactId>
    <version>2.2.3.RELEASE</version>
</dependency>

使用网关的Filter做鉴权

package com.dazuizui.gateway.filter;

import com.dazuizui.api.utils.JwtUtil;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.Ordered;
import org.springframework.http.HttpCookie;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Component;
import org.springframework.util.MultiValueMap;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

/**
 * @author 哇塞大嘴好帅
 * @blog   www.dazuizui.com
 * @Time   2020/7/11 21:05
 * @Text   DaZui_Blog项目的网关拦截器
 */
@Component
public class AuthFilter implements GlobalFilter, Ordered {
    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        //跳转登入界面验证工具,如果为假就不跳转登入页面 如果跳转就跳转
        boolean goUrlHuser = false;
        //获取cookie
        MultiValueMap<String, HttpCookie> cookies = exchange.getRequest().getCookies();
        //获取url
        String url = exchange.getRequest().getURI().toString();
        //如果访问的url存在/huser/就需要鉴权
        if (url.contains("/huser/")){
            //存放token的值
            String tokenstr = "";

            //判断是否存在token记录
            if (cookies.getFirst("token") == null){
                System.out.println("[Filter] : 不存在token");
                goUrlHuser = true;
            }else{
                HttpCookie tokencookie = cookies.getFirst("token");
                tokenstr = tokencookie.getValue();
                System.out.println("接收到的token"+tokenstr);
            }

            //判断用户token是否过期或者恶意登入
            if (!goUrlHuser){
                String userdate = null;
                try {
                    userdate = JwtUtil.analysisJWT(tokenstr);
                } catch (Exception e) {
                    System.out.println("用户可能存在恶意登入或者登入token过期");
                    goUrlHuser = true;
                }
            }

            //如果没有登入或者token存在问题跳转登入页面
            if (goUrlHuser){
                //重定向到
                url = "http://127.0.0.1:8080/hlogin/index.html";
                System.out.println(url);
                exchange.getResponse().setStatusCode(HttpStatus.SEE_OTHER);
                exchange.getResponse().getHeaders().set(HttpHeaders.LOCATION,url);

                return exchange.getResponse().setComplete();
            }
        }
        return chain.filter(exchange);
    }

    @Override
    public int getOrder() {
        return -10;
    }
}

校验账号密码是否正确

/**
 * 判断账号密码是否正确,如果正确跳转到重定向的界面,如果不正确跳转登入界面重新登入
 * @param username     账号
 * @param password     密码
 * @return
 */
@CrossOrigin
@PostMapping(value="/userlogin/ShiroLogin")
@ResponseBody
public String logim(@RequestParam("username") String username,@RequestParam("password") String password, HttpSession session, HttpServletResponse response) throws IOException {
    //判断账号密码是否正确
    if (username.equals("root") && password.equals("admin")) {
        String jwtstring = JwtUtil.createJWT(user);
   		return jwtstring;
    }else{
        return "false";
    }

}

前端部分

<!DOCTYPE html>
<html lang="en"
      xmlns:th="http://www.w3.org/1999/xhtml">
<head>
    <meta name="renderer" content="webkit">
    <meta http-equiv="X-UA-Compatible" content="IE=EmulateIE7">
    <meta http-equiv="X-UA-COMPATIBLE" content="IE=edge,chrome=1"/>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
    <meta name="description" content="">
    <meta name="author" content="">
    <title>登入</title>
    <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@4.5.0/dist/css/bootstrap.min.css" integrity="sha384-9aIt2nRpC12Uk9gS9baDl411NQApFmC26EwAOH8WgZl5MYYxFfc+NcPb1dKGj7Sk" crossorigin="anonymous">
    <link rel="stylesheet" type="text/css" href="http://175.24.118.135:8080/static/dazuiblog/userlogin.css">
</head>

<body class="text-center">
<div id="Sing" class="main animated zoomIn" v-cloak>
    <form  v-on:submit.prevent="submit()">
        <img class="mb-4" src="http://175.24.118.135:8080/static/asserts/img/Logo/Logo.png" alt="" width="250" height="250">
        <h1 class="h3 mb-3 font-weight-normal"></h1>
        <label class="sr-only">Username</label>
        <input type="text" class="form-control" placeholder="username" required="" autofocus="" id="username" name="username" v-model="userlogin.username">
        <label class="sr-only">Password</label>
        <input type="password" class="form-control" placeholder="password" required="" id="password" name="password" v-model="userlogin.password">
        <button class="btn btn-lg btn-primary btn-block" type="submit"  id="sub"  v-bind:hidden="formbutton" style="width:300px;height: 50px;"> 登入</button> 
        <button class="btn btn-primary" type="button" disabled v-bind:hidden="!formbutton" style="width:300px;height: 50px;"> 
            <span class="spinner-grow spinner-grow-sm" role="status" aria-hidden="true"></span>
            正在登入中......
        </button>
        还没有账号?<a href="http://175.24.118.135:8080/hlogin/enroll.html">点击我注册</a>
        <p class="mt-5 mb-3 text-muted">© 2020 - 2020 &nbsp;大嘴开发团队</p>
    </form>
</div>
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
<script src="https://unpkg.com/vue/dist/vue.js"></script>
<script src="http://175.24.118.135:8080/static/dazuiblog/js/dazuiblog.js"></script>
<script src="https://cdn.bootcss.com/qs/6.5.2/qs.min.js"></script>
<script>
    var vm = new Vue({
       el:  "#Sing",
       data: {
           formbutton: false,
           userlogin:{
               username: null,
               password: null,
           },
           msg: null,
       },

       methods: {
           //表单提交
           submit() {
               //更换按钮为不可点击 
               this.formbutton = true;
               var qs = Qs;
               var formData = new FormData(event.target);
               axios.post("http://127.0.0.1:8080/userlogin/ShiroLogin",qs.stringify({
                   username:this.userlogin.username,
                   password:this.userlogin.password,
               })).then(function (response) {
                   //登入成功
                   if (response.data != false){
                    //将登入信息存入cookie
                    setCookie("token",response.data);
                    window.location.href="http://127.0.0.1:8080/hblog/blogindex.html";
                   } else{
                       //登入失败
                       alert("您输入的账号或者密码错误");
                       window.location.href="http://127.0.0.1:8080/hlogin/index.html";
                   }
                })
           }
       }
    });
</script>
</body>
</html>

js脚本语句

   //设置cookie
   function setCookie (name, value) {
        if (value) {
            var Days = 365
            var exp = new Date()
            exp.setTime(exp.getTime() + Days * 24 * 60 * 60 * 1000)
            document.cookie = name + '=' + escape(value) + ';expires=' + exp.toGMTString()+"; path=/";
        }
    }
    //获取cookie
    function  getCookie(NameOfCookie) {
                if (document.cookie.length > 0) {
                    begin = document.cookie.indexOf(NameOfCookie + "=");
                    if (begin !== -1) {
                        begin += NameOfCookie.length + 1;
                        end = document.cookie.indexOf(";", begin);
                        if (end === -1) end = document.cookie.length;
                        return unescape(document.cookie.substring(begin, end));
                    }
                }
                return null;
            }

    //获取url参数
    function getQueryVariable(variable)
    {
        var query = window.location.search.substring(1);
        var vars = query.split("&");
        for (var i=0;i<vars.length;i++) {
            var pair = vars[i].split("=");
            if(pair[0] == variable){return pair[1];}
        }
        return(false);
    }
  • 9
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
SpringCloud是基于Spring框架的分布式系统开发框架,它提供了丰富的分布式系统解决方案。而Sa-Token是一个轻量级的Java权限认证与授权框架,提供了简单易用的权限控制功能。 在SpringCloud中整合Sa-Token可以为我们的分布式系统提供更加安全可靠的权限认证与授权机制。具体步骤如下: 1. 在SpringCloud的微服务架构中,将Sa-Token配置为一个独立的授权认证中心,可以独立部署,也方便对其进行管理和维护。 2. 在每个微服务中引入Sa-Token的依赖,通过配置Sa-Token的相关属性,实现微服务的用户登录与认证。同时,可以使用Sa-Token提供的注解进行权限控制,例如@RequiresPermissions注解可以对接口或方法进行权限校验。 3. 在微服务之间进行访问时,可以通过Sa-TokenToken验证机制,对调用方进行身份认证。因此,每个微服务需要验证并解析Token,以确保请求方的合法性。 4. Sa-Token提供了灵活的权限授权机制,可以根据业务需求配置不同的角色和权限管理。在SpringCloud中,我们可以根据微服务的不同职能划分角色,为每个角色分配相应的权限。通过角色与权限的配置,实现对不同微服务接口的精确控制。 通过将Sa-Token整合到SpringCloud中,我们可以实现整个系统的统一权限管理。无论是对用户的认证与授权,还是对接口的权限控制,都可以通过Sa-Token轻松实现。这不仅提高了系统的安全性,同时也简化了系统的开发与维护工作。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

哇塞大嘴好帅(DaZuiZui)

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

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

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

打赏作者

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

抵扣说明:

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

余额充值