首页 > 其他分享 >JWT oss登录

JWT oss登录

时间:2023-05-31 18:00:20浏览次数:73  
标签:map return String 登录 JWT oss jwt public

可参考:https://juejin.cn/post/7106702145520402468

流程

image

组成部分

1.Header(头) 作用:记录令牌类型、签名算法等 例如:{“alg":"HS256","type","JWT}

2.Payload(有效载荷)作用:携带一些用户信息 例如{"userId":"1","username":"mayikt"}

3.Signature(签名)作用:防止Token被篡改、确保安全性 例如 计算出来的签名,一个字符串

1.第一部分:header (头部)
{
Typ=“jwt” —类型为jwt
Alg:“HS256” --加密算法为hs256//主要是用于验签,防止数据被篡改
}
2.第二部分:playload(载荷) 携带存放的数据 用户名称、用户头像之类 注意铭感数据
标准中注册的声明 (建议但不强制使用) :
iss: jwt签发者
sub: jwt所面向的用户
aud: 接收jwt的一方
exp: jwt的过期时间,这个过期时间必须要大于签发时间
nbf: 定义在什么时间之前,该jwt都是不可用的.
iat: jwt的签发时间
jti: jwt的唯一身份标识,主要用来作为一次性token,从而回避重放攻击。
3.第三部分:Signature(签名)

jwt和session区别

session是保存在服务端的,而JWT是保存在客户端的

  • 基于session的认证流程

用户在浏览器中输入用户名和密码,服务器通过密码校验后生成一个session并保存到数据库
服务器为用户生成一个sessionId,并将具有sesssionId的cookie放置在用户浏览器中,在后续的请求中都将带有这个cookie信息进行访问
服务器获取cookie,通过获取cookie中的sessionId查找数据库判断当前请求是否有效

  • 基于JWT的认证流程

用户在浏览器中输入用户名和密码,服务器通过密码校验后生成一个token并保存到数据库
前端获取到token,存储到cookie或者local storage中,在后续的请求中都将带有这个token信息进行访问
服务器获取token值,通过查找数据库判断当前token是否有效

安全性

JWT的payload使用的是base64编码的,因此在JWT中不能存储敏感数据。而session的信息是存在服务端的,相对来说更安全

性能

经过编码之后JWT将非常长,cookie的限制大小一般是4k,cookie很可能放不下,所以JWT一般放在local storage里面。并且用户在系统中的每一次http请求都会把JWT携带在Header里面,HTTP请求的Header可能比Body还要大。而sessionId只是很短的一个字符串,因此使用JWT的HTTP请求比使用session的开销大得多

一次性

无状态是JWT的特点,但也导致了这个问题,JWT是一次性的。想修改里面的内容,就必须签发一个新的JWT

无法废弃

一旦签发一个JWT,在到期之前就会始终有效,无法中途废弃。若想废弃,一种常用的处理手段是结合redis

续签

如果使用JWT做会话管理,传统的cookie续签方案一般都是框架自带的,session有效期30分钟,30分钟内如果有访问,有效期被刷新至30分钟。一样的道理,要改变JWT的有效时间,就要签发新的JWT。
最简单的一种方式是每次请求刷新JWT,即每个HTTP请求都返回一个新的JWT。这个方法不仅暴力不优雅,而且每次请求都要做JWT的加密解密,会带来性能问题。另一种方法是在redis中单独为每个JWT设置过期时间,每次访问时刷新JWT的过期时间
选择JWT或session
JWT有很多缺点,但是在分布式环境下不需要像session一样额外实现多机数据共享,虽然seesion的多机数据共享可以通过粘性session、session共享、session复制、持久化session、terracoa实现seesion复制等多种成熟的方案来解决这个问题。但是JWT不需要额外的工作,使用JWT不香吗?并且JWT一次性的缺点可以结合redis进行弥补

实现

  • java

添加依赖

  <dependency>
            <groupId>io.jsonwebtoken</groupId>
            <artifactId>jjwt</artifactId>
            <version>0.9.1</version>
        </dependency>

        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
        </dependency>

代码编写

//controller层
@RestController
@RequestMapping("/user")
public class UserController {

    @Resource
    private UserService userService;

    @RequestMapping(value = "/login", method = RequestMethod.POST)
    public JwtResponse login(@RequestParam(name = "userName") String userName,
                             @RequestParam(name = "passWord") String passWord){
        String jwt = "";
        try {
            jwt = userService.login(userName, passWord);
            return JwtResponse.success(jwt);
        } catch (Exception e) {
            e.printStackTrace();
            return JwtResponse.fail(jwt);
        }
    }


    @Resource
    private JwtUtils jwtUtil;

    @RequestMapping("/test")
    public Map<String, Object> test(@RequestParam("jwt") String jwt) {
        //这个步骤可以使用自定义注解+AOP编程做解析jwt的逻辑,这里为了简便就直接写在controller里
        Claims claims = null;
        HashMap<String, Object> map = new HashMap<>();
        try {
             claims = jwtUtil.parseJWT(jwt);
        } catch (Exception e) {
            map.put("code", "1");
            map.put("msg", "已过期,请重新登录");
           return map;
        }

        String name = claims.get("name", String.class);
        String age = claims.get("age", String.class);
        map.put("name", name);
        map.put("age", age);
        map.put("code", "0");
        map.put("msg", "请求成功");
        return map;
    }

//service层
public interface UserService {

     String login(String username, String password) throws Exception;
}

@Service
public class UserServiceImpl implements UserService {

    @Resource
    private JwtUtils jwtUtil;

    @Resource
    private UserMapper userMapper;

    @Override
    public String login(String userName, String passWord) throws Exception {
        //登录验证
        User user = userMapper.findByUserNameAndPassword(userName, passWord);
        if (user == null) {
            return null;
        }
        //如果能查出,则表示账号密码正确,生成jwt返回
        String uuid = UUID.randomUUID().toString().replace("-", "");
        HashMap<String, Object> map = new HashMap<>();
        map.put("name", user.getName());
        map.put("age", user.getAge());
      //ttl设置  下面是一分钟示例(一分钟后过期)
        return jwtUtil.createJWT(uuid, "login subject", 60 * 1000L, map);
    }
	
	
	//核心
@Component
public class JwtUtils {

    @Value("${jwt.secretKey}")
    private String secretKey;

    public String createJWT(String id, String subject, long ttlMillis, Map<String, Object> map) throws Exception {

        //头部信息,不设置也是默认这个值
        Map<String, Object> header = new HashMap<>(2);
        header.put("Type", "Jwt");
        header.put("alg", "HS256");

        JwtBuilder builder = Jwts.builder()
                .setHeader(header)
                .setId(id)
                .setSubject(subject) // 发行者
                .setIssuedAt(new Date()) // 发行时间
                .signWith(SignatureAlgorithm.HS256, secretKey) // 签名类型 与 密钥
                .compressWith(CompressionCodecs.DEFLATE);// 对载荷进行压缩
        if (!CollectionUtils.isEmpty(map)) {
            builder.setClaims(map);
        }
        if (ttlMillis > 0) {
            builder.setExpiration(new Date(System.currentTimeMillis() + ttlMillis));
        }
        return builder.compact();// 拼接header + payload
    }


    public Claims parseJWT(String jwtString) {
        return Jwts.parser().setSigningKey(secretKey)
                .parseClaimsJws(jwtString)
                .getBody();
    }

    public static void main(String[] args) {
        Date date1 = new Date(System.currentTimeMillis());
        Date date = new Date(System.currentTimeMillis() + 60 * 1000L);
        System.out.println(date1);
        System.out.println(date);
    }
}
}



//mapper
@Component
public class UserMapper {

    private static final Map<String, User> map = new HashMap<>();

    static {
        User value = new User();
        value.setUsername("zs");
        value.setPassword("123");
        value.setName("林大大");
        value.setAge("999");
        map.put("zs", value);
    }
    public User findByUserNameAndPassword(String userName, String passWord) {
        User user = map.get(userName);
        if (!Objects.isNull(user)) {
            if (passWord.equals(user.getPassword())) {
                return user;
            }
        }
        return null;
    }
}


//common

@Data
@AllArgsConstructor
@NoArgsConstructor
public class BaseResponse {

    private String code;

    private String msg;

    public static BaseResponse success() {
        return new BaseResponse("0", "成功");
    }

    public static BaseResponse fail() {
        return new BaseResponse("1", "失败");
    }
    //构造器、getter、setter方法
}



@EqualsAndHashCode(callSuper = true)
@Data
public
class JwtResponse extends BaseResponse {

    private String jwtData;

    private String code;

    private String msg;

    public JwtResponse(String code, String msg, String jwtData) {
        this.code = code;
        this.msg = msg;
        this.jwtData = jwtData;
    }

    public static JwtResponse success(String jwtData) {
        BaseResponse success = BaseResponse.success();
        return new JwtResponse(success.getCode(), success.getMsg(), jwtData);
    }

    public static JwtResponse fail(String jwtData) {
        BaseResponse fail = BaseResponse.fail();
        return new JwtResponse(fail.getCode(), fail.getMsg(), jwtData);
    }
    //构造器、getter、setter方法
}


application.yml
## 用户生成jwt字符串的secretKey
jwt:
  secretKey: ak47


标签:map,return,String,登录,JWT,oss,jwt,public
From: https://www.cnblogs.com/lin5923/p/17446933.html

相关文章

  • JWT
    jwt优点使用cookie的话,不支持跨域,使用jwt的话放置到请求头里面支持跨域支持移动端jwt的认证流程第一步:通过用户名和密码进行验证的Post请求,https类型第二步:验证通过后将用户的基本信息,作为jwt的载体,和jwt的头部分别进行base64编码,形成一个JWTToken字符串第三步:将JWTToke......
  • SpringBoot整合OSS文件上传
    一、注册阿里云账号并开通OSS服务1、登录阿里云账号2、创建一个bucket3、创建子用户对自用户分配权限,打开操作OSS的全部权限(也可根据业务需求进行更改)4、配置上传跨域规则任何来源:*允许方法:POST任何请求头Headers:*二、文件上传方式1、服务器直传方式每个O......
  • 前端 React + vite + Typescript 后端 java + springmvc + jwt 跨域 解决方案
    首先后端配置跨域:web.xml文件: <!--配置跨域--><filter><filter-name>header</filter-name><filter-class>org.zhiyi.config.Cross</filter-class></filter><filter-mapping><......
  • 报错问题谷粒商城 Oss endpoint can‘t be empty
    报错信息:Causedby:java.lang.IllegalArgumentException:Ossendpointcan’tbeempty.网上查了一下说有两种可能第一种是springboot和springcloud版本不对应第二种错误说的是oss.yml格式错误 建议优先检查yml格式我的因为那天改配置的时候被家里猫按到了,然后没有发现,检......
  • java开发jwt示例
    pom文件引入<dependency><groupId>com.fasterxml.jackson.core</groupId><artifactId>jackson-databind</artifactId><version>2.15.1</version></dependency>......
  • dockerfile镜像私有仓库需要https登录验证改成http
    ERROR:failedtodorequest:Head"https://192.168.16.185:8088/v2/jenkins/python_common_api/manifests/base":http:servergaveHTTPresponsetoHTTPSclientDockerfile:1--------------------1|>>>FROM192.168.16.185:8088/jenkins/p......
  • bashrc添加环境变量当用户登录时生效,等号两边不要有空格
    bashrc是Linux系统中的一种shell脚本,当用户登录时,bashrc文件会被自动执行。它是一个用于加载环境变量和自定义脚本的地方,可以用来定制您的系统环境。在本文中,我们将详细介绍如何在bashrc文件中添加环境变量。一、基础知识在开始添加环境变量之前,您需要了解bashrc文件及其作用。......
  • 常见LOSS函数之Cross Entropy(交叉熵)
    常见LOSS函数之CrossEntropy(交叉熵)交叉熵是分类问题常用的损失函数。熵熵表示稳定性或者说惊喜度,熵越高表示越稳定,其惊喜度就越低。示例一般用H(p)表示熵交叉熵交叉熵=熵+散度散度代表分布的重叠程度,散度越高重合度越少。当两个分布p和q相等时,散度等于0,此时交叉熵......
  • drf-JWT认证
    目录一jwt介绍和原理1.1cookie,session,token发展历史1.2认证过程1.3JWT的构成1.3.1header1.3.2payload1.3.3signature二base64编码和解码2.1base64使用2.2base64的用途三jwt开发流程四drf-jwt快速使用五drf-jwt定制返回格式六自定义签发和认证6.1drf-jwt自定义用户......
  • drf-jwt
    jwt原理使用jwt认证和使用session认证的区别session是将用户信息存放在数据库中,在客户端存一个随机的字符串,下次用户提交的时候将字符串与数据库中存在的进行比较jwt是根据用户提交的信息,产生一个token,将token返回给客户端,下次用户提交的时候,将token进行解析三段式#这是一......