携带用户名密码的登陆请求经过网关转发到授权中心微服务,授权微服务远程调用user-service中的登陆方法验证用户名和密码,验证成功之后,将userId,userName作为载荷加入到token中,在将token写入到cookie中
@GetMapping("query")
public ResponseEntity<User> queryUser(@RequestParam("username")String username,@RequestParam("password")String password){
User user = this.userService.queryUser(username, password);
if (user == null){
return ResponseEntity.badRequest().build();
}
return ResponseEntity.ok(user);
}
public User queryUser(String username, String password) {
// 根据用户名去数据库中查找用户
User record = new User();
record.setUsername(username);
User user = this.userMapper.selectOne(record);
if (user == null){
return null;
}
// 获取盐,对用户输入的密码进行加盐加密
password = CodecUtils.md5Hex(password, user.getSalt());
// 和数据库中的密码进行比较
if (StringUtils.equals(password, user.getPassword())){
return user;
}
return null;
}
由于是远程调用的方式,而不是直接请求到controller接口,我们将controller中的方法写成一个接口
public interface UserApi {
@GetMapping("query")
User queryUser(@RequestParam("username")String username, @RequestParam("password")String password);
}
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>leyou-authartifactId>
<groupId>com.leyou.authgroupId>
<version>1.0.0-SNAPSHOTversion>
parent>
<modelVersion>4.0.0modelVersion>
<groupId>com.leyou.authgroupId>
<artifactId>leyou-auth-commonartifactId>
<dependencies>
<dependency>
<groupId>org.apache.commonsgroupId>
<artifactId>commons-lang3artifactId>
dependency>
<dependency>
<groupId>io.jsonwebtokengroupId>
<artifactId>jjwtartifactId>
<version>0.9.0version>
dependency>
<dependency>
<groupId>joda-timegroupId>
<artifactId>joda-timeartifactId>
dependency>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-testartifactId>
dependency>
dependencies>
project>
auth-service依赖:
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>leyou-authartifactId>
<groupId>com.leyou.authgroupId>
<version>1.0.0-SNAPSHOTversion>
parent>
<modelVersion>4.0.0modelVersion>
<groupId>com.leyou.authgroupId>
<artifactId>leyou-auth-serviceartifactId>
<dependencies>
<dependency>
<groupId>org.springframework.cloudgroupId>
<artifactId>spring-cloud-starter-netflix-eureka-clientartifactId>
dependency>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-webartifactId>
dependency>
<dependency>
<groupId>com.leyou.usergroupId>
<artifactId>leyou-user-interfaceartifactId>
<version>1.0.0-SNAPSHOTversion>
dependency>
<dependency>
<groupId>org.springframework.cloudgroupId>
<artifactId>spring-cloud-starter-openfeignartifactId>
dependency>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-testartifactId>
dependency>
<dependency>
<groupId>com.leyou.authgroupId>
<artifactId>leyou-auth-commonartifactId>
<version>1.0.0-SNAPSHOTversion>
dependency>
<dependency>
<groupId>com.leyou.commongroupId>
<artifactId>leyou-commonartifactId>
<version>1.0.0-SNAPSHOTversion>
dependency>
dependencies>
project>
auth-service配置:
server:
port: 8087
spring:
application:
name: auth-service
eureka:
client:
service-url:
defaultZone: http://localhost:10086/eureka
registry-fetch-interval-seconds: 10
instance:
lease-expiration-duration-in-seconds: 15
lease-renewal-interval-in-seconds: 5
leyou:
jwt:
secret: leyou@Login(Auth}*^31)&heiMa% # secret生成公钥和私钥的密文
pubKeyPath: D:\IdeaProjects\springCloud\tmp\rsa\rsa.pub # 公钥地址
priKeyPath: D:\IdeaProjects\springCloud\tmp\rsa\rsa.pri # 私钥地址
expire: 30 #token过期时间,单位分钟
cookieName: LY_TOKEN #cookie的名字
用到的几个主要的工具类
RsaUtils
:生成和获取私钥公钥的工具类
package com.leyou.common.utils;
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.security.*;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
public class RsaUtils {
/**
* 从文件中读取公钥
*
* @param filename 公钥保存路径,相对于classpath
* @return 公钥对象
* @throws Exception
*/
public static PublicKey getPublicKey(String filename) throws Exception {
byte[] bytes = readFile(filename);
return getPublicKey(bytes);
}
/**
* 从文件中读取私钥
*
* @param filename 私钥保存路径,相对于classpath
* @return 私钥对象
* @throws Exception
*/
public static PrivateKey getPrivateKey(String filename) throws Exception {
byte[] bytes = readFile(filename);
return getPrivateKey(bytes);
}
/**
* 获取公钥
*
* @param bytes 公钥的字节形式
* @return
* @throws Exception
*/
public static PublicKey getPublicKey(byte[] bytes) throws Exception {
X509EncodedKeySpec spec = new X509EncodedKeySpec(bytes);
KeyFactory factory = KeyFactory.getInstance("RSA");
return factory.generatePublic(spec);
}
/**
* 获取私钥
*
* @param bytes 私钥的字节形式
* @return
* @throws Exception
*/
public static PrivateKey getPrivateKey(byte[] bytes) throws Exception {
PKCS8EncodedKeySpec spec = new PKCS8EncodedKeySpec(bytes);
KeyFactory factory = KeyFactory.getInstance("RSA");
return factory.generatePrivate(spec);
}
/**
* 根据密文(secret),生存rsa公钥和私钥,并写入指定文件
*
* @param publicKeyFilename 公钥文件路径
* @param privateKeyFilename 私钥文件路径
* @param secret 生成密钥的密文
* @throws IOException
* @throws NoSuchAlgorithmException
*/
public static void generateKey(String publicKeyFilename, String privateKeyFilename, String secret) throws Exception {
KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
SecureRandom secureRandom = new SecureRandom(secret.getBytes());
keyPairGenerator.initialize(1024, secureRandom);
KeyPair keyPair = keyPairGenerator.genKeyPair();
// 获取公钥并写出
byte[] publicKeyBytes = keyPair.getPublic().getEncoded();
writeFile(publicKeyFilename, publicKeyBytes);
// 获取私钥并写出
byte[] privateKeyBytes = keyPair.getPrivate().getEncoded();
writeFile(privateKeyFilename, privateKeyBytes);
}
private static byte[] readFile(String fileName) throws Exception {
return Files.readAllBytes(new File(fileName).toPath());
}
private static void writeFile(String destPath, byte[] bytes) throws IOException {
File dest = new File(destPath);
if (!dest.exists()) {
dest.createNewFile();
}
Files.write(dest.toPath(), bytes);
}
}
JwtUtils
:生成和解析token的工具类
package com.leyou.common.utils;
import com.leyou.common.pojo.UserInfo;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jws;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import org.joda.time.DateTime;
import java.security.PrivateKey;
import java.security.PublicKey;
public class JwtUtils {
/**
* 私钥加密token
*
* @param userInfo 载荷中的数据
* @param privateKey 私钥
* @param expireMinutes 过期时间,单位分钟
* @return
* @throws Exception
*/
public static String generateToken(UserInfo userInfo, PrivateKey privateKey, int expireMinutes) throws Exception {
return Jwts.builder()
.claim(JwtConstans.JWT_KEY_ID, userInfo.getId())
.claim(JwtConstans.JWT_KEY_USER_NAME, userInfo.getUsername())
.setExpiration(DateTime.now().plusMinutes(expireMinutes).toDate())
.signWith(SignatureAlgorithm.RS256, privateKey)
.compact();
}
/**
* 私钥加密token
*
* @param userInfo 载荷中的数据
* @param privateKey 私钥字节数组
* @param expireMinutes 过期时间,单位分钟
* @return
* @throws Exception
*/
public static String generateToken(UserInfo userInfo, byte[] privateKey, int expireMinutes) throws Exception {
return Jwts.builder()
.claim(JwtConstans.JWT_KEY_ID, userInfo.getId())
.claim(JwtConstans.JWT_KEY_USER_NAME, userInfo.getUsername())
.setExpiration(DateTime.now().plusMinutes(expireMinutes).toDate())
.signWith(SignatureAlgorithm.RS256, RsaUtils.getPrivateKey(privateKey))
.compact();
}
/**
* 公钥解析token
*
* @param token 用户请求中的token
* @param publicKey 公钥
* @return
* @throws Exception
*/
private static Jws<Claims> parserToken(String token, PublicKey publicKey) {
return Jwts.parser().setSigningKey(publicKey).parseClaimsJws(token);
}
/**
* 公钥解析token
*
* @param token 用户请求中的token
* @param publicKey 公钥字节数组
* @return
* @throws Exception
*/
private static Jws<Claims> parserToken(String token, byte[] publicKey) throws Exception {
return Jwts.parser().setSigningKey(RsaUtils.getPublicKey(publicKey))
.parseClaimsJws(token);
}
/**
* 获取token中的用户信息
*
* @param token 用户请求中的令牌
* @param publicKey 公钥
* @return 用户信息
* @throws Exception
*/
public static UserInfo getInfoFromToken(String token, PublicKey publicKey) throws Exception {
Jws<Claims> claimsJws = parserToken(token, publicKey);
Claims body = claimsJws.getBody();
return new UserInfo(
ObjectUtils.toLong(body.get(JwtConstans.JWT_KEY_ID)),
ObjectUtils.toString(body.get(JwtConstans.JWT_KEY_USER_NAME))
);
}
/**
* 获取token中的用户信息
*
* @param token 用户请求中的令牌
* @param publicKey 公钥
* @return 用户信息
* @throws Exception
*/
public static UserInfo getInfoFromToken(String token, byte[] publicKey) throws Exception {
Jws<Claims> claimsJws = parserToken(token, publicKey);
Claims body = claimsJws.getBody();
return new UserInfo(
ObjectUtils.toLong(body.get(JwtConstans.JWT_KEY_ID)),
ObjectUtils.toString(body.get(JwtConstans.JWT_KEY_USER_NAME))
);
}
}
CookieUtils
:操作cookie的工具类
package com.leyou.common.utils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.net.URLEncoder;
/**
*
* Cookie 工具类
*
*/
public final class CookieUtils {
static final Logger logger = LoggerFactory.getLogger(CookieUtils.class);
/**
* 得到Cookie的值, 不编码
*
* @param request
* @param cookieName
* @return
*/
public static String getCookieValue(HttpServletRequest request, String cookieName) {
return getCookieValue(request, cookieName, false);
}
/**
* 得到Cookie的值,
*
* @param request
* @param cookieName
* @return
*/
public static String getCookieValue(HttpServletRequest request, String cookieName, boolean isDecoder) {
Cookie[] cookieList = request.getCookies();
if (cookieList == null || cookieName == null){
return null;
}
String retValue = null;
try {
for (int i = 0; i < cookieList.length; i++) {
if (cookieList[i].getName().equals(cookieName)) {
if (isDecoder) {
retValue = URLDecoder.decode(cookieList[i].getValue(), "UTF-8");
} else {
retValue = cookieList[i].getValue();
}
break;
}
}
} catch (UnsupportedEncodingException e) {
logger.error("Cookie Decode Error.", e);
}
return retValue;
}
/**
* 得到Cookie的值,
*
* @param request
* @param cookieName
* @return
*/
public static String getCookieValue(HttpServletRequest request, String cookieName, String encodeString) {
Cookie[] cookieList = request.getCookies();
if (cookieList == null || cookieName == null){
return null;
}
String retValue = null;
try {
for (int i = 0; i < cookieList.length; i++) {
if (cookieList[i].getName().equals(cookieName)) {
retValue = URLDecoder.decode(cookieList[i].getValue(), encodeString);
break;
}
}
} catch (UnsupportedEncodingException e) {
logger.error("Cookie Decode Error.", e);
}
return retValue;
}
/**
* 生成cookie,并指定编码
* @param request 请求
* @param response 响应
* @param cookieName name
* @param cookieValue value
* @param encodeString 编码
*/
public static final void setCookie(HttpServletRequest request, HttpServletResponse response, String cookieName, String cookieValue, String encodeString) {
setCookie(request,response,cookieName,cookieValue,null,encodeString, null);
}
/**
* 生成cookie,并指定生存时间
* @param request 请求
* @param response 响应
* @param cookieName name
* @param cookieValue value
* @param cookieMaxAge 生存时间
*/
public static final void setCookie(HttpServletRequest request, HttpServletResponse response, String cookieName, String cookieValue, Integer cookieMaxAge) {
setCookie(request,response,cookieName,cookieValue,cookieMaxAge,null, null);
}
/**
* 设置cookie,不指定httpOnly属性
*/
public static final void setCookie(HttpServletRequest request, HttpServletResponse response, String cookieName, String cookieValue, Integer cookieMaxAge, String encodeString) {
setCookie(request,response,cookieName,cookieValue,cookieMaxAge,encodeString, null);
}
/**
* 设置Cookie的值,并使其在指定时间内生效
*
* @param cookieMaxAge
* cookie生效的最大秒数
*/
public static final void setCookie(HttpServletRequest request, HttpServletResponse response, String cookieName, String cookieValue, Integer cookieMaxAge, String encodeString, Boolean httpOnly) {
try {
if(StringUtils.isBlank(encodeString)) {
encodeString = "utf-8";
}
if (cookieValue == null) {
cookieValue = "";
} else {
cookieValue = URLEncoder.encode(cookieValue, encodeString);
}
Cookie cookie = new Cookie(cookieName, cookieValue);
if (cookieMaxAge != null && cookieMaxAge > 0)
cookie.setMaxAge(cookieMaxAge);
if (null != request)// 设置域名的cookie
cookie.setDomain(getDomainName(request));
cookie.setPath("/");
if(httpOnly != null) {
cookie.setHttpOnly(httpOnly);
}
response.addCookie(cookie);
} catch (Exception e) {
logger.error("Cookie Encode Error.", e);
}
}
/**
* 得到cookie的域名
*/
private static final String getDomainName(HttpServletRequest request) {
String domainName = null;
String serverName = request.getRequestURL().toString();
if (serverName == null || serverName.equals("")) {
domainName = "";
} else {
serverName = serverName.toLowerCase();
serverName = serverName.substring(7);
final int end = serverName.indexOf("/");
serverName = serverName.substring(0, end);
final String[] domains = serverName.split("\\.");
int len = domains.length;
if (len > 3) {
// www.xxx.com.cn
domainName = domains[len - 3] + "." + domains[len - 2] + "." + domains[len - 1];
} else if (len <= 3 && len > 1) {
// xxx.com or xxx.cn
domainName = domains[len - 2] + "." + domains[len - 1];
} else {
domainName = serverName;
}
}
if (domainName != null && domainName.indexOf(":") > 0) {
String[] ary = domainName.split("\\:");
domainName = ary[0];
}
return domainName;
}
}
JwtConstans
:定义载荷常量
public abstract class JwtConstans {
public static final String JWT_KEY_ID = "id";
public static final String JWT_KEY_USER_NAME = "username";
}
JwtProperties
:对应配置文件中的配置信息,和私钥公钥对象
//读取配置文件中前缀是leyou.jwt的配置信息赋值给下面的成员变量
@ConfigurationProperties(prefix = "leyou.jwt")
public class JwtProperties {
private String secret; // 密钥
private String pubKeyPath; // 公钥路径
private String priKeyPath; // 私钥路径
private int expire; // token过期时间
private PublicKey publicKey; // 公钥
private PrivateKey privateKey;// 私钥
private String cookieName; // cookie名字
private static final Logger logger = LoggerFactory.getLogger(JwtProperties.class);
/**
* @PostContruct:在构造方法执行之后执行该方法
* 初始化publicKey,privateKey
*/
@PostConstruct
public void init(){
try {
File pubKey = new File(pubKeyPath);
File priKey = new File(priKeyPath);
if (!pubKey.exists() || !priKey.exists()) {
// 生成公钥和私钥
RsaUtils.generateKey(pubKeyPath, priKeyPath, secret);
}
// 获取公钥和私钥
this.publicKey = RsaUtils.getPublicKey(pubKeyPath);
this.privateKey = RsaUtils.getPrivateKey(priKeyPath);
} catch (Exception e) {
logger.error("初始化公钥和私钥失败!", e);
throw new RuntimeException();
}
}
//getter setter..
}
UserClient
:远程调用接口
@FeignClient("user-service")
public interface UserClient extends UserApi {
}
AuthController
:
package com.leyou.auth.controller;
import com.leyou.auth.config.JwtProperties;
import com.leyou.auth.service.AuthService;
import com.leyou.common.pojo.UserInfo;
import com.leyou.common.utils.CookieUtils;
import com.leyou.common.utils.JwtUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.CookieValue;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* @auther Mr.Liao
* @date 2019/5/23 18:43
*/
@Controller
//启用配置类,读取配置文件的信息
@EnableConfigurationProperties(JwtProperties.class)
public class AuthController {
@Autowired
private AuthService authService;
@Autowired
private JwtProperties jwtProperties;
/**
* 登录并将token写入到cookie中
* @param username
* @param password
* @param request
* @param response
* @return
*/
@PostMapping("login")
public ResponseEntity<Void> accredit(@RequestParam("username")String username,
@RequestParam("password")String password,
HttpServletRequest request,
HttpServletResponse response){
String token = this.authService.accredit(username, password);
if (StringUtils.isBlank(token)){
return ResponseEntity.status(HttpStatus.UNAUTHORIZED).build();
}
// 将token写入Cookie
CookieUtils.setCookie(request,response,this.jwtProperties.getCookieName(),token,this.jwtProperties.getExpire() * 60);
return ResponseEntity.ok(null);
}
/**
* 验证用户是否登陆,返回user对象,更新token
*/
@GetMapping("verify")
public ResponseEntity<UserInfo> verify(@CookieValue("LY_TOKEN")String token, HttpServletRequest request, HttpServletResponse response){
try {
// 使用JwtUtils解析Cookie中的token,获取用户信息
UserInfo user = JwtUtils.getInfoFromToken(token, this.jwtProperties.getPublicKey());
// 未登录,返回401 未授权,状态码
if (user == null){
return ResponseEntity.status(HttpStatus.UNAUTHORIZED).build();
}
//已登录,生成新的token,加入到Cookie中
token = JwtUtils.generateToken(user, this.jwtProperties.getPrivateKey(), this.jwtProperties.getExpire());
CookieUtils.setCookie(request,response,this.jwtProperties.getCookieName(),token,this.jwtProperties.getExpire()*60);
return ResponseEntity.ok(user);
} catch (Exception e) {
e.printStackTrace();
}
return ResponseEntity.status(HttpStatus.UNAUTHORIZED).build();
}
}
AuthService
:
package com.leyou.auth.service;
import com.leyou.auth.client.UserClient;
import com.leyou.auth.config.JwtProperties;
import com.leyou.common.pojo.UserInfo;
import com.leyou.common.utils.JwtUtils;
import com.leyou.user.pojo.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
/**
* @auther Mr.Liao
* @date 2019/5/23 18:45
*/
@Service
public class AuthService {
@Autowired
private UserClient userClient;
@Autowired
private JwtProperties jwtProperties;
public String accredit(String username, String password) {
// 根据用户名和密码查询,这里在user-service服务查询user为null时,返回400状态码,feign报异常,所以要try
User user;
try {
user = this.userClient.queryUser(username, password);
} catch (Exception e) {
e.printStackTrace();
System.out.println("feign远程调用user-service查询出现错误");
return null;
}
// 判断user是否为null
if (user == null){
return null;
} else {
// jwtUtils通过私钥生成token
try {
// 载荷
UserInfo userInfo = new UserInfo();
userInfo.setId(user.getId());
userInfo.setUsername(user.getUsername());
String token = JwtUtils.generateToken(userInfo, this.jwtProperties.getPrivateKey(), this.jwtProperties.getExpire());
return token;
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
}
}
启动类:
@SpringBootApplication
@EnableFeignClients
@EnableDiscoveryClient
public class LeyouAuthApplication {
public static void main(String[] args) {
SpringApplication.run(LeyouAuthApplication.class, args);
}
}
解决cookie写入问题
由于我们配置了域名的映射
在nginx中配置
同时在zuul网关中配置
zuul:
prefix: /api
routes:
item-service: /item/** #路由到后台商品的微服务
search-service: /search/** #路由到前台搜索微服务
user-service: /user/** #路由到用户微服务
auth-service: /auth/** #路由到授权微服务
cart-service: /cart/** #路由到购物车微服务
order-service: /order/** #路由到订单车微服务
add-host-header: true #携带头信息(域名)
sensitive-headers: #值为空覆盖敏感默认头信息,能够将cookie设置到响应头
判断用户是否登陆,从cookie中获取token,然后通过公钥解析token,判断token是否有效。同时要判断哪些请求需要验证用户是否登陆,比如加入购物车或者关于订单的请求都要验证是否登陆,在配置中配置那些不需要验证的请求路径信息,配置文件如下:
server:
port: 10010
spring:
application:
name: leyou-gateway
eureka:
client:
registry-fetch-interval-seconds: 5 # 拉取服务的时间
service-url:
defaultZone: http://localhost:10086/eureka
zuul:
prefix: /api
routes:
item-service: /item/** #路由到后台商品的微服务
search-service: /search/** #路由到前台搜索微服务
user-service: /user/** #路由到用户微服务
auth-service: /auth/** #路由到授权微服务
cart-service: /cart/** #路由到购物车微服务
order-service: /order/** #路由到订单车微服务
add-host-header: true #携带头信息(域名)
sensitive-headers: #值为空覆盖敏感默认头信息,能够将cookie设置到响应头
leyou:
jwt:
pubKeyPath: D:\IdeaProjects\springCloud\tmp\rsa\rsa.pub # 公钥地址
cookieName: LY_TOKEN
filter:
allowPaths:
- /api/auth
- /api/search
- /api/user/register
- /api/user/check
- /api/user/code
- /api/item
通过两个配置属性类来获取配置属性
JwtProperties
package com.leyou.gateway.config;
import com.leyou.common.utils.RsaUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.context.properties.ConfigurationProperties;
import javax.annotation.PostConstruct;
import java.security.PublicKey;
@ConfigurationProperties(prefix = "leyou.jwt")
public class JwtProperties {
private String pubKeyPath; // 公钥路径
private PublicKey publicKey; // 公钥
private String cookieName; // cookie名字
private static final Logger logger = LoggerFactory.getLogger(JwtProperties.class);
/**
* @PostContruct:在构造方法执行之后执行该方法
*/
@PostConstruct
public void init(){
try {
// 获取公钥
this.publicKey = RsaUtils.getPublicKey(pubKeyPath);
} catch (Exception e) {
logger.error("初始化公钥和私钥失败!", e);
throw new RuntimeException();
}
}
//getter setter
}
FilterProperties
@ConfigurationProperties(prefix = "leyou.filter")
public class FilterProperties {
private List<String> allowPaths;
public List<String> getAllowPaths() {
return allowPaths;
}
public void setAllowPaths(List<String> allowPaths) {
this.allowPaths = allowPaths;
}
}
LoginFilter
:过滤器
package com.leyou.gateway.filter;
import com.leyou.common.utils.CookieUtils;
import com.leyou.common.utils.JwtUtils;
import com.leyou.gateway.config.FilterProperties;
import com.leyou.gateway.config.JwtProperties;
import com.netflix.zuul.ZuulFilter;
import com.netflix.zuul.context.RequestContext;
import com.netflix.zuul.exception.ZuulException;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Component;
import javax.servlet.http.HttpServletRequest;
import java.util.List;
/**
* @auther Mr.Liao
* @date 2019/5/23 20:45
*/
@Component
@EnableConfigurationProperties({
JwtProperties.class, FilterProperties.class})
public class LoginFilter extends ZuulFilter {
@Autowired
private JwtProperties jwtProperties;
@Autowired
private FilterProperties filterProperties;
//前置过滤器,在路由之前过滤
@Override
public String filterType() {
return "pre";
}
//过滤器执行的顺序,级别
@Override
public int filterOrder() {
return 10;
}
// return true 执行run方法,在白名单中就不进行拦截
@Override
public boolean shouldFilter() {
// 获取白名单
List<String> allowPaths = this.filterProperties.getAllowPaths();
// 初始化运行上下文
RequestContext context = RequestContext.getCurrentContext();
// 获取request对象
HttpServletRequest request = context.getRequest();
String url = request.getRequestURI();
for (String allowPath : allowPaths) {
if (StringUtils.contains(url, allowPath)){
return false;
}
}
return true;
}
@Override
public Object run() throws ZuulException {
// 初始化运行上下文
RequestContext context = RequestContext.getCurrentContext();
// 获取request对象
HttpServletRequest request = context.getRequest();
//获取token
String token = CookieUtils.getCookieValue(request, this.jwtProperties.getCookieName());
try {
JwtUtils.getInfoFromToken(token,this.jwtProperties.getPublicKey());
} catch (Exception e) {
//如果解析出现异常,则说明token无效,没有token时也会出现异常
e.printStackTrace();
context.setSendZuulResponse(false);
context.setResponseStatusCode(HttpStatus.UNAUTHORIZED.value());
}
return null;
}
}