天天看點

java jwt token reids_SpringBoot整合shiro+jwt+redis - 無狀态token登入(二)授權篇

更多最新技術文章歡迎大家通路我的個人部落格○( ^皿^)っ豆腐别館

上文總覽篇中,相信大家已經對接下來要做的事情有了總體思路及印象。總言之我們要做的就隻有兩件事,一是授權,二即是鑒權。

讓我們先從授權開始,何為授權?在這裡簡單地來講就是要頒發token。何時頒發?毫無疑問,無非就是在登入/注冊成功之後。至于上文中提到的根據RefreshToken自動重新整理AccessToken,我将之歸置為token重新整理,代碼實作于後續篇章說明。

一、Maven配置

com.auth0

java-jwt

${java-jwt.version}

二、Application配置

server:

port: 8001

spring:

application:

name: springboot-shiro-jwt-sso

# profiles: springboot-shiro-jwt-sso

## Redis配置 - start

redis:

# Redis資料庫索引(預設為0)

database: 1

# Redis伺服器位址

host: 127.0.0.1

# Redis伺服器連接配接端口

port: 6379

# Redis伺服器連接配接密碼(預設為空)

# password: "doufuplus"

# 連接配接逾時時間(毫秒)

timeout: 5000

jedis:

pool:

# 連接配接池最大連接配接數(使用負值表示沒有限制)

max-active: 8

# 連接配接池最大阻塞等待時間(使用負值表示沒有限制)

max-wait: -1

# 連接配接池中的最大空閑連接配接

max-idle: 8

# 連接配接池中的最小空閑連接配接

min-idle: 0

## Redis配置 - end

## 時間格式配置 - start

jackson:

serialization:

write-dates-as-timestamps: true

## 時間格式配置 - end

## product配置 - start

info:

app.name: springboot-shiro-jwt-sso

company.name: doufuplus

build.artifactId: $project.artifactId$

build.modelVersion: $project.modelVersion$

## product配置 - end

## 日志配置 - start

logging:

level:

com.nfgj.medical.service: DEBUG

## 日志配置 - end

## 其它配置 - start

config:

# JWT認證加密私鑰(Base64加密)

encrypt-jwtKey: U0JBUElOENhspJrzkyNjQ1NA

# AccessToken過期時間(秒)

accessToken-expireTime: 600

# RefreshToken過期時間(秒)

refreshToken-expireTime: 604800

## 其它配置 - end

三、頒發Token

token的頒發并未有什麼難度,主要是生成AccessToken放置于Header給前端。再生成RefreshToken儲存于服務端即可。此處使用redis儲存。

@PostMapping("/login")

public Result login(String account, String password, HttpServletResponse response) {

try {

if (!("doufuplus".equals(account) && "123456".equals(password))) {

return new Result(ResultCode.PASSWORD_ERROR, "account or password error.");

}

// 清除可能存在的shiro權限資訊緩存

if (redis.hasKey(RedisConstant.PREFIX_SHIRO_CACHE + account)) {

redis.del(RedisConstant.PREFIX_SHIRO_CACHE + account);

}

// 設定RefreshToken,時間戳為目前時間戳,直接設定即可(不用先删後設,會覆寫已有的RefreshToken)

String currentTimeMillis = String.valueOf(System.currentTimeMillis());

redis.set(RedisConstant.PREFIX_SHIRO_REFRESH_TOKEN + account, currentTimeMillis,

Integer.parseInt(refreshTokenExpireTime));

// 從Header中Authorization傳回AccessToken,時間戳為目前時間戳

String token = JwtUtil.sign(account, currentTimeMillis);

response.setHeader("Authorization", token);

response.setHeader("Access-Control-Expose-Headers", "Authorization");

return new Result().OK();

} catch (Exception e) {

e.printStackTrace();

return new Result(ResultCode.ERROR, e.getMessage());

}

}

四、清除Token

沒有買賣就沒有傷害,有登入就會有退出。token的清除主要是做兩件事:

清除可能存在的shiro權限資訊

清除RefreshToken

@RequestMapping("/logout")

public Result logout() {

try {

String token = "";

// 擷取頭部資訊

Enumeration headerNames = request.getHeaderNames();

while (headerNames.hasMoreElements()) {

String key = (String) headerNames.nextElement();

String value = request.getHeader(key);

if ("Authorization".equalsIgnoreCase(key)) {

token = value;

}

}

// 校驗token

if (StringUtils.isBlank(token)) {

return new Result(ResultCode.PARAM_ERROR);

}

String account = JwtUtil.getClaim(token, JwtConstant.ACCOUNT);

if (StringUtils.isBlank(account)) {

return new Result(ResultCode.NOT_LOGIN, "token失效或不正确.");

}

// 清除shiro權限資訊緩存

if (redis.hasKey(RedisConstant.PREFIX_SHIRO_CACHE + account)) {

redis.del(RedisConstant.PREFIX_SHIRO_CACHE + account);

}

// 清除RefreshToken

redis.del(RedisConstant.PREFIX_SHIRO_REFRESH_TOKEN + account);

return new Result().OK();

} catch (Exception e) {

e.printStackTrace();

return new Result(ResultCode.ERROR, e.getMessage());

}

}

五、示範說明

登入成功,傳回10200

java jwt token reids_SpringBoot整合shiro+jwt+redis - 無狀态token登入(二)授權篇

登入成功-1.png

檢視Header,Authorization傳回AccessToken資訊

java jwt token reids_SpringBoot整合shiro+jwt+redis - 無狀态token登入(二)授權篇

登入成功-2.png