使用jwt实现登录功能

一、什么是jwt

1.什么是session

要想知道什么是jwt,就要先知道什么是session,可以这样理解session,处于安全问题,有一些数据需要保存在服务端,服务端根据客户端的sessionId可以识别到它的session,然后进行数据的处理。
session一般存储一些简单,并且比较重要的信息,例如用户id,用户登录状态,权限等。

在这里插入图片描述

注意,如果用户禁用了cookie,那么session也就无法使用,因为session使用cookie中携带的唯一id才能在服务器中找到

2.什么是jwt?

jwt全程是json web token。是由用户以用户名、密码登录,服务端验证后,会生成一个token,返回给客户端,客户端在下次访问的过程中携带这个token,服务端责每次验证这个token。
在这里插入图片描述

3.为什么使用jwt而不使用session

  1. session是将客户端数据储存在服务器的内存,当客服端的数据过多,服务器的内存开销大;
  2. session的数据储存在某台服务器,在分布式的项目中无法做到共享;
  3. jwt的安全性更好。

总而言之,如果使用了分布式,切只能在session和jwt里面选的时候,就一定要选jwt。

二、jwt原理

1. header 头:

包含令牌的类型和使用的签名算法

{
	"alg":"HS625", // 签名算法
	"type":"JWT" // 令牌类型
}

将请求头进行base64加密就构成了第一部分

2.payload 荷载

荷载就是装载数据的地方,包含声明(有关用户实体和其他数据的声明),使用Base64进行编码,
可以把payload荷载想象成session的数据,session虽然存放在服务器内存,也要防止一些意外,比如有工作人员监守自盗盗取密码,因此,session里面不可以存放敏感信息

{
	"username": "zhangsan",
	"dataAuth": "beijing"
}

3.signature 签名

将header和payload经过base64加密后的数据经过加盐后进行二次加密。
盐值仅仅保存在服务器端,不能泄露,如果泄露容易导致客户端自己签发token,例如:即使没有经过登录步骤,知道用户名username,用自己签发token去访问一些数据权限敏感的数据。

三、使用实现登录

1.引入依赖

implementions('io.jsonwebtoken:jjwt:0.7.0')

2.准备配置

# token私钥,储存在只有签发和解析token的服务端
jwt.secret=123456
# 过期时间,单位为毫秒,这里是24*60*60*1000,24小时内有效
jwt.expire=86400000

3.创建和解析JWT的工具类

@ConfigurationProperties(prefix = "jwt")
@Component
@Data
public class JwtConfig {

	private String secret;

    private long expire;

    /**
     * 签发jwt
     *
     * @param user
     * @return
     */
    public String createJWT(User user) {
        Date date = new Date();
        Date expireDate = new Date(date.getTime() + expire);
        Map<String, Object> claims = new HashMap<>();
        claims.put("name", user.getUsername());
        claims.put("id", user.getId());
        String jwt = Jwts.builder()
                // 设置装载内容
                .setClaims(claims)
                // 签发时间
                .setIssuedAt(date)
                // 过期时间
                .setExpiration(expireDate)
                // jwt主体,用来存放jwt的所有人,可以存用户id或者角色id
                .setSubject(user.getName())
                .compact();
        return jwt;
    }
    
    /**
     * 解析JWT
     *
     * @param jwt
     * @return
     */
    public Claims parseJWT(String jwt) {
        Claims claims = Jwts.parser().setSigningKey(secret).parseClaimsJwt(jwt).getBody();
        return claims;
    }
    
}

4.登录时签发token

    @RequestMapping("login")
    public Map<String, Object> login(@RequestParam(name = "name") String name, @RequestParam(name = "passWord") String passWord) {
        User user = userService.findByUsernameAndPassword(name, passWord);
        if (null == user ) {
            throw new ControllerException("501", "用户名或密码错误");
        }
        String token = jwtConfig.createJWT(user);
        map.put("token", token);
        return map;
    }

5.过滤器及其配置类

@Configuration
public class WebConfig implements WebMvcConfigurer {
    @Resource
    private LoginInterceptor loginInterceptor;

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(loginInterceptor).addPathPatterns("/**");
    }
}
@Component
public class LoginInterceptor extends HandlerInterceptorAdapter {
    
    @Resource
    private JwtConfig jwtConfig;

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
        String url = request.getRequestURI();
        // 如果包含login,则直接去验证用户名密码,不需要去验证token,可以利用这里设置白名单
        if (url.contains("/login")) {
            return true;
        }
        String token = request.getHeader(jwtConfig.getHeader());
        if (StringUtils.isEmpty(token)) {
            token = request.getParameter(jwtConfig.getHeader());
        }
        if (null == token || token.isEmpty()) {
            return false;
        }
        Claims claims = jwtConfig.parseJWT(token);
		String userName = claims.get("name", String.class);
        request.setAttribute("userName", subject);
        return true;
    }


    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        return true;
    }
}
  • 5
    点赞
  • 29
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
### 回答1: 以下是使用 JWT 实现登录功能的 Java 代码示例: ```java import io.jsonwebtoken.Claims; import io.jsonwebtoken.Jwts; import io.jsonwebtoken.SignatureAlgorithm; import javax.crypto.spec.SecretKeySpec; import java.security.Key; import java.util.Date; public class JwtUtil { // 设置JWT过期时间,这里设置为1小时 private static final long EXPIRATION_TIME = 3600000; // JWT密码 private static final String SECRET = "mySecretKey"; // Token前缀 private static final String TOKEN_PREFIX = "Bearer"; // 存放Token的Header Key private static final String HEADER_STRING = "Authorization"; // 生成JWT Token public static String generateToken(String username) { // 生成JWT的时间 long nowMillis = System.currentTimeMillis(); Date now = new Date(nowMillis); // 设置JWT过期时间 Date expirationDate = new Date(nowMillis + EXPIRATION_TIME); // 设置JWT的Header SignatureAlgorithm signatureAlgorithm = SignatureAlgorithm.HS256; byte[] apiKeySecretBytes = SECRET.getBytes(); Key signingKey = new SecretKeySpec(apiKeySecretBytes, signatureAlgorithm.getJcaName()); // 设置JWT的Payload Claims claims = Jwts.claims().setSubject(username); // 生成JWT Token String token = Jwts.builder() .setClaims(claims) .setIssuedAt(now) .setExpiration(expirationDate) .signWith(signingKey, signatureAlgorithm) .compact(); return token; } // 验证JWT Token public static boolean validateToken(String token) { try { // 验证JWT Token是否合法 Jwts.parser().setSigningKey(SECRET.getBytes()).parseClaimsJws(token); return true; } catch (Exception e) { return false; } } // 从JWT Token中获取用户名 public static String getUsernameFromToken(String token) { Claims claims = Jwts.parser() .setSigningKey(SECRET.getBytes()) .parseClaimsJws(token) .getBody(); return claims.getSubject(); } } ``` 在登录接口中调用 `generateToken` 方法生成 JWT Token,然后将生成的 Token 返回给客户端,客户端将 Token 保存在本地。在后续的请求中,客户端需要在请求的 Header 中携带 Token,服务端从 Header 中获取 Token,调用 `validateToken` 方法验证 Token 的合法性,然后从 Token 中获取用户名,进而完成登录认证。 ### 回答2: Java代码使用JWT实现登录功能的步骤如下: 1. 首先,需要导入相关的依赖包。可以使用Maven或Gradle构建工具来管理依赖项。需要导入的依赖包有:jjwt、javax.servlet-api等。 2. 创建一个JWTUtil类,该类用于生成和验证JWT。其中,生成JWT的方法如下: ```java import io.jsonwebtoken.Jwts; import io.jsonwebtoken.SignatureAlgorithm; import java.util.Date; public class JWTUtil { private static final String SECRET_KEY = "密钥"; private static final long EXPIRATION_TIME = 1800000; // 过期时间为30分钟 public static String generateToken(String username) { return Jwts.builder() .setSubject(username) .setExpiration(new Date(System.currentTimeMillis() + EXPIRATION_TIME)) .signWith(SignatureAlgorithm.HS512, SECRET_KEY) .compact(); } } ``` 3. 创建一个LoginController类,用于处理登录请求。在该类中,可以使用JWTUtil的generateToken方法生成JWT,并将其返回给前端。 ```java import javax.servlet.http.HttpServletRequest; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RestController; @RestController public class LoginController { @PostMapping("/login") public String login(@RequestBody User user, HttpServletRequest request) { // 根据用户名和密码验证用户信息 if (user.getUsername().equals("admin") && user.getPassword().equals("admin")) { String token = JWTUtil.generateToken(user.getUsername()); return token; } else { return "登录失败"; } } } ``` 在这个示例中,假设用户对象User中包含了用户名和密码字段。 4. 前端登录请求发送到后台时,会调用LoginController的login方法。如果用户名和密码验证成功,将生成JWT并返回给前端。前端可以将该JWT存储起来,并在后续的请求中通过HTTP头或其他方式发送给服务端进行验证。 需要注意的是,JWT中包含了用户信息,因此在收到JWT后,服务端可以通过解析JWT获取用户信息,而无需再次查询数据库验证用户信息。 以上就是用Java代码使用JWT实现登录功能的简要说明。当然,实际应用中可能还需要完成其他的操作,比如JWT的验证等。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值