1:首先對JWT進行簡單介紹
參考官網:https://jwt.io/
什么是JWT:Json web token,是為了在網路應用環境間傳遞宣告而執行的一種基于JSON的開放標準,適合用于分布式站點的單點登錄(SSO)場景,一般被用來在身份提供者和服務提供者間傳遞被認證的用戶身份資訊,以便于從資源服務器獲取資源
2:Java使用方法(以下代碼中涉及三個工具類,本文并未提及其代碼,如有需要,請下載檔案:jwtUtils.zip,里面是三個工具類,解壓放入專案即可)
地址:https://franciseric.oss-cn-shanghai.aliyuncs.com/bokeyuan/jwtUtils.zip
2.1:引入依賴
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-api</artifactId>
<version>0.11.0</version>
</dependency>
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-impl</artifactId>
<version>0.11.0</version>
</dependency>
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-jackson</artifactId>
<version>0.11.0</version>
</dependency>
2.2:授權中心組態檔需要的引數
auth: jwt: //公私鑰路徑 后面兩個檔案后綴為了方便區分 此處授權中心需要公鑰私鑰的生成,所以兩個路徑都需要,而提供資源的服務則只需要其中之一,比如使用公鑰解密,私鑰加密
// 這個公鑰私鑰地址一定要改成自己電腦對應放公鑰私鑰的地址
privateKeyPath: E:\\JavaEESoftware\\JavaData\\auth_key\\rsa.pri publicKeyPath: E:\\JavaEESoftware\\JavaData\\auth_key\\rsa.pub //簽名 增加密碼的復雜性 secret: (&^&^*^*%*&$&^(*&)(*&()^*(^(IUGhoindsoihfowanoisjndfoihn645654 //cook名稱 cookieName: AUTH-TOKEN //過期時間 分鐘 exprieTime: 180
2.3:撰寫組態檔引數的物體類
@ConfigurationProperties("auth.jwt")
@Data
@Slf4j
public class JwtProperties {
private String privateKeyPath;
private String publicKeyPath;
private String secret;
private String cookieName;
private Integer exprieTime;
//使用jdk的兩個key 它們的作用是能夠保存公鑰私鑰內容,方便獲取
private PublicKey publicKey;
private PrivateKey privateKey;
}
2.4:撰寫獲取公鑰私鑰的方法,以及生成的方法
@Data @Slf4j
@ConfigurationProperties("auth.jwt") public class JwtProperties { private String privateKeyPath; private String publicKeyPath; private String secret; private String cookieName; private Integer exprieTime; private PublicKey publicKey; private PrivateKey privateKey; @PostConstruct public void init() { try { File priFile = new File(privateKeyPath); File pubFile = new File(publicKeyPath); //判斷檔案是否存在 if (!priFile.exists() || !pubFile.exists()) {
//RsaUtils這個工具在jwtUtils檔案中,下載即可用 RsaUtils.generateKey(publicKeyPath, privateKeyPath, secret); } //存在就讀取 并賦值給鍵 this.privateKey = RsaUtils.getPrivateKey(privateKeyPath); this.publicKey = RsaUtils.getPublicKey(publicKeyPath); } catch (Exception e) { log.error("生成公鑰私鑰失敗"); } } }
2.5:撰寫測驗controller
@RestController @RequestMapping("auth") public class AuthController { @Autowired private AuthService authService; @Autowired private JwtProperties jwtProperties; @PostMapping("accredit") public Resp<Object> accredit(@RequestParam("username")String userName, @RequestParam("password")String password, HttpServletRequest request, HttpServletResponse response){ String token = this.authService.accredit(userName, password); // 4.把jwt型別的token放入cookie中 CookieUtils.setCookie(request, response, this.jwtProperties.getCookieName(), token, this.jwtProperties.getExprieTime() * 60); return Resp.ok(null); } }
2.6:撰寫service
@Servicepublic class AuthService { @Autowired private JwtProperties jwtProperties; @Autowired private UmsClient umsClient; public String accredit(String userName, String password) { // 1.呼叫用戶查詢介面 此處是已經呼叫別的微服務,那么如果是測驗的話,完全可以先寫死這些資訊,先查看公私鑰是否正常,以及token是否生成 UserEntity userEntity = this.umsClient.queryUserByPad(userName, password).getData();// 2.不存在直接回傳 if (userEntity== null) {
//此處例外是自定義例外,代碼拿去另行指定即可 throw new UserException("用戶名或者密碼輸入有誤!"); } try { // 3.制作jwt Map<String, Object> map = new HashMap<>(); map.put("userId", userEntity.getId()); map.put("userName", userEntity.getUsername());
/**
此處就是jwt生成token,使用的是私鑰,那么資源提供方,只需要將公鑰配置即可此處也可以使用公鑰加密,那么資源提供方則反之使用私鑰即可解密
這么map就是一個用戶資訊,在資源提供方解密獲得這個用戶后,這個用戶就可以獲取相應的資源訪問權限
/ return JwtUtils.generateToken(map, this.jwtProperties.getPrivateKey(), this.jwtProperties.getExprieTime()); } catch (Exception e) { e.printStackTrace(); } return null; } }
2.7:啟動類需要增加一個注解,來啟用配置物體類
@SpringBootApplication
@EnableFeignClients
@EnableDiscoveryClient
@EnableConfigurationProperties({JwtProperties.class})//就是這個配置,配置類名叫什么,就寫什么即可
public class AuthApplication {
public static void main(String[] args) {
SpringApplication.run(AuthApplication.class, args);
}
}
2.8:打開postman,來進行測驗(省略,,,)
postman測驗,顯示正常,但是這個cookie可能沒有出現,但是在請求頭我們可以看的到,其實瀏覽器端已經能夠設定進去了,只是postman有時候無法設定,解決方案是:使用內網穿透,映射到Auth這個服務的埠,然后使用穿透的地址+controller訪問地址,就能夠使得postman成功設定cookie
3:getway網關工程使用jwt(getway網關使用參考另一篇博客即可)
server: port: 21217 spring: cloud: gateway: routes: - id: user-route uri: lb://user-service #斷言 predicates: - Path=/user/** - id: auth-route uri: lb://auth-service #斷言 predicates: - Path=/api/auth/** filters: - RewritePath=/api(?<segment>/?.*), $\{segment} auth: jwt:
//由于加密使用的是私鑰,所以此處使用公鑰來進行解密 publicKeyPath: E:\\JavaEESoftware\\GmallNew\\gmall-jwt-key\\rsa.pub cookieName: AUTH_TOKEN
3.1:在網關工程里撰寫相應的配置物體類,此處說的配置物體類,是我們自定義的配置,比如auth:開頭的
@ConfigurationProperties("auth.jwt")
@Data
@Slf4j
public class JwtProperties {
private String publicKeyPath;
private String cookieName;
private PublicKey publicKey;
@PostConstruct
public void init() {
try {
this.publicKey = RsaUtils.getPublicKey(publicKeyPath);
} catch (Exception e) {
log.error("讀取公鑰失敗");
}
}
}
3.2:撰寫過濾器
@Component public class AuthGetwayFilter implements GatewayFilter { @Autowired private JwtProperties jwtProperties; @Override public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) { //獲取物件 ServerHttpRequest request = exchange.getRequest(); ServerHttpResponse response = exchange.getResponse(); //從cookie中獲取jwt型別的token MultiValueMap<String, HttpCookie> cookies = request.getCookies(); //判斷cookie是否為null if(CollectionUtils.isEmpty(cookies) || !cookies.containsKey(this.jwtProperties.getCookieName())){ //攔截這個請求 設定狀態碼為身份認證未通過 response.setStatusCode(HttpStatus.UNAUTHORIZED); return response.setComplete(); } HttpCookie cookie = cookies.getFirst(jwtProperties.getCookieName()); //判斷是否為空 if(cookie==null || StringUtils.isEmpty(cookie.getValue())){ //攔截這個請求 設定狀態碼為身份認證未通過 response.setStatusCode(HttpStatus.UNAUTHORIZED); return response.setComplete(); } try { //決議jwt JwtUtils.getInfoFromToken(cookie.getValue(),this.jwtProperties.getPublicKey()); //放行請求 return chain.filter(exchange); } catch (Exception e) { //出現例外 攔截這個請求 設定狀態碼為身份認證未通過 response.setStatusCode(HttpStatus.UNAUTHORIZED); return response.setComplete(); } } }
3.3:還需撰寫一個工廠類來操作這個過濾器
@Component public class AuthGatewayFilterFactory extends AbstractGatewayFilterFactory { @Autowired private AuthGetwayFilter authGetwayFilter; @Override public GatewayFilter apply(Object config) {
//這里可以使用內部類來做,但是顯得有點不好看,就分開了 return authGetwayFilter; } }
3.4:在配置中使用過濾器
server: port: 21217 spring: cloud: gateway: routes: - id: user-route uri: lb://user-service #斷言 predicates: - Path=/user/** filters://在需要進行登錄授權的服務網關filters下,增加這個 - Auth即可對這個路徑進行過濾 - Auth - id: auth-route uri: lb://auth-service #斷言 predicates: - Path=/api/auth/** filters: - RewritePath=/api(?<segment>/?.*), $\{segment} auth: jwt: //由于加密使用的是私鑰,所以此處使用公鑰來進行解密 publicKeyPath: E:\\JavaEESoftware\\GmallNew\\gmall-jwt-key\\rsa.pub cookieName: AUTH_TOKEN
3.3:還是一樣的,啟動類需要增加注解,將物體類寫入,以及pom檔案增加jwt的依賴
3.4:最后使用網關,測驗User的相關服務,會發現,提示未授權,那么這個時候,就需要瀏覽器攜帶token的cookie,才能訪問這個服務
3.5:測驗截圖
3.5.1:沒有cookie訪問用戶介面

3.5.2:訪問auth 獲得授權

3.5.3:再次訪問用戶測驗介面

至此,簡單jwt實作已經完成
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/169931.html
標籤:其他
上一篇:模擬的草地
