網頁登錄功能的實現?
Json web token (JWT), 是為了在網絡應用環境間傳遞聲明而執行的一種基于JSON的開放標準((RFC 7519).該token被設計為緊湊且安全的,特別適用于分布式站點的單點登錄(SSO)場景。JWT的聲明一般被用來在身份提供者和服務提供者間傳遞被認證的用戶身份信息,以便于從資源服務器獲取資源,也可以增加一些額外的其它業務邏輯所必須的聲明信息,該token也可直接被用于認證,也可被加密。
登錄注冊功能實現?身份認證在這種場景下,一旦用戶完成了登陸,在接下來的每個請求中包含JWT,可以用來驗證用戶身份以及對路由,服務和資源的訪問權限進行驗證。由于它的開銷非常小,可以輕松的在不同域名的系統中傳遞,所有目前在單點登錄(SSO)中比較廣泛的使用了該技術。 信息交換在通信的雙方之間使用JWT對數據進行編碼是一種非常安全的方式,由于它的信息是經過簽名的,可以確保發送者發送的信息是沒有經過偽造的。
{"alg": "HS265","typ": "JWT"
}
{"name": "admin","pass": 123
}
<!--引入jwt--><dependency><groupId>com.auth0</groupId><artifactId>java-jwt</artifactId><version>3.4.0</version></dependency><!--引入mybatis--><dependency><groupId>org.mybatis.spring.boot</groupId><artifactId>mybatis-spring-boot-starter</artifactId><version>2.1.3</version></dependency><!--引入mysql--><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>8.0.15</version></dependency>
server.port=8989spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.url=jdbc:mysql://8.192.12.37:3306/test?characterEncoding=UTF-8
spring.datasource.username=root
spring.datasource.password=rootmybatis.type-aliases-package=com.boot.jwt.entity
mybatis.mapper-locations=com/boot/jwt/mapper/*.xmllogging.level.com.baizhi.dao=debug
package com.boot.jwt.config;import com.auth0.jwt.JWT;
import com.auth0.jwt.JWTVerifier;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.exceptions.JWTCreationException;
import com.auth0.jwt.exceptions.JWTDecodeException;
import com.auth0.jwt.exceptions.JWTVerificationException;
import com.auth0.jwt.interfaces.DecodedJWT;
import com.boot.jwt.entity.User;import java.util.Date;/*** @author laz* @date 2022/09/09 14:55*/
public class TokenUtil {//token到期時間60sprivate static final long EXPIRE_TIME= 60*1000;//密鑰鹽private static final String TOKEN_SECRET="123456qwertyuiop789";/*** 創建一個token* @param user* @return*/public static String sign(User user){String token=null;try {Date expireAt=new Date(System.currentTimeMillis()+EXPIRE_TIME);token = JWT.create()//發行人.withIssuer("auth0")//存放數據.withClaim("username",user.getUsername()).withClaim("password",user.getPassword())//過期時間.withExpiresAt(expireAt).sign(Algorithm.HMAC256(TOKEN_SECRET));} catch (IllegalArgumentException|JWTCreationException je) {}return token;}/*** 對token進行驗證* @param token* @return*/public static Boolean verify(String token){try {//創建token驗證器JWTVerifier jwtVerifier=JWT.require(Algorithm.HMAC256(TOKEN_SECRET)).withIssuer("auth0").build();DecodedJWT decodedJWT=jwtVerifier.verify(token);System.out.println("認證通過:");System.out.println("username: " + TokenUtil.getUserName(token));System.out.println("過期時間: " + decodedJWT.getExpiresAt());} catch (IllegalArgumentException |JWTVerificationException e) {//拋出錯誤即為驗證不通過return false;}return true;}/*** 獲取用戶名*/public static String getUserName(String token){try{DecodedJWT jwt=JWT.decode(token);return jwt.getClaim("username").asString();}catch (JWTDecodeException e){return null;}}
}
package com.boot.jwt.config;import com.alibaba.fastjson.JSONObject;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;/*** @author laz* @date 2022/09/09 14:56*/
@Component
public class TokenInterceptor implements HandlerInterceptor {@Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {//跨域請求會首先發一個option請求,直接返回正常狀態并通過攔截器if(request.getMethod().equals("OPTIONS")){response.setStatus(HttpServletResponse.SC_OK);return true;}//獲取到tokenString token = request.getHeader("token");if (token!=null){boolean result= TokenUtil.verify(token);if (result){System.out.println("通過攔截器");return true;}}try {JSONObject json=new JSONObject();json.put("msg","token verify fail");json.put("code","500");response.getWriter().append(json.toString());System.out.println("認證失敗,未通過攔截器");} catch (Exception e) {return false;}return false;}}
package com.boot.jwt.config;import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;import java.util.ArrayList;
import java.util.List;/*** @author laz* @date 2022/09/09 13:56*/
@Configuration
public class WebConfiguration implements WebMvcConfigurer {@Autowiredprivate TokenInterceptor tokenInterceptor;/*** 配置攔截器、攔截路徑* 每次請求到攔截的路徑,就會去執行攔截器中的方法* @param*/@Overridepublic void addInterceptors(InterceptorRegistry registry) {List<String> excludePath = new ArrayList<>();//排除攔截,除了登錄,其他都攔截excludePath.add("/test/login");registry.addInterceptor(tokenInterceptor).addPathPatterns("/**").excludePathPatterns(excludePath);WebMvcConfigurer.super.addInterceptors(registry);}}
package com.boot.jwt.entity;import lombok.Data;/*** @author laz* @date 2022/09/09 14:54*/
@Data
public class User {private String id;private String username;private String password;
}
package com.boot.jwt.mapper;import com.boot.jwt.entity.User;/*** @author laz* @date 2022/09/09 14:54*/
public interface UserMapper {/*** 登錄* @param user* @return*/User login(User user);
}
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
<mapper namespace="com.boot.jwt.mapper.UserMapper"><select id="login" parameterType="com.boot.jwt.entity.User" resultType="com.boot.jwt.entity.User">select * from user where username=#{username} and password = #{password}</select></mapper>
package com.boot.jwt.service;import com.boot.jwt.entity.User;
import com.boot.jwt.utils.LoginDto;/*** @author laz* @date 2022/09/09 14:54*/
public interface IUserService {/*** 登錄接口* @param user* @return*/LoginDto login(User user);}
package com.boot.jwt.service.impl;import com.boot.jwt.config.TokenUtil;
import com.boot.jwt.entity.User;
import com.boot.jwt.mapper.UserMapper;
import com.boot.jwt.service.IUserService;
import com.boot.jwt.utils.LoginDto;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;/*** @author laz* @date 2022/09/09 14:54*/
@Service
public class IUserServiceImpl implements IUserService {@Autowiredprivate UserMapper userMapper;@Overridepublic LoginDto login(User user) {LoginDto loginDto = new LoginDto();User login = userMapper.login(user);if (login == null){loginDto.setCode(400);loginDto.setMsg("賬號或密碼錯誤!");return loginDto;}String token= TokenUtil.sign(login);loginDto.setCode(200);loginDto.setMsg("登錄成功!");loginDto.setUser(login);loginDto.setToken(token);return loginDto;}
}
package com.boot.jwt.controller;import com.boot.jwt.entity.User;
import com.boot.jwt.service.IUserService;
import com.boot.jwt.utils.LoginDto;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;/*** @author laz* @date 2022/09/09 14:58*/
@RestController
@RequestMapping("/test")
public class LoginController {@Autowiredprivate IUserService userService;/*** 登錄* @param user* @return*/@PostMapping("/login")public LoginDto login(@RequestBody User user){LoginDto login = userService.login(user);return login;}/*** 測試* @return*/@RequestMapping("/test")public Object test(){return "訪問成功!";}}
到這里,代碼就編寫完成了,下面開始測試。
先調用測試接口
可以看到,接口被攔截了。
接下來調用login接口,獲取token:
再次調用測試接口,帶上token:
可以看到,接口成功訪問。
版权声明:本站所有资料均为网友推荐收集整理而来,仅供学习和研究交流使用。
工作时间:8:00-18:00
客服电话
电子邮件
admin@qq.com
扫码二维码
获取最新动态