完成单点登录

编写登录接口

接下来,我们需要在auth编写一个接口,对外提供登录授权服务。基本流程如下:

  • 客户端携带用户名和密码请求登录

  • 授权中心调用用户中心接口,根据用户名和密码查询用户信息

  • 如果用户名密码正确,能获取用户,否则登录失败

  • 如果校验成功,则生成JWT并返回

编写远程调用接口

创建ums-interface工程:

pom.xml中的依赖,参照其他interface工程。并在ums和auth工程中引入该接口工程

UmsApi:

public interface UmsApi {/*** 根据用户名和密码查询用户* @param username* @param password* @return*/@GetMapping("ums/member/query")public Resp queryUser(@RequestParam("username") String username,@RequestParam("password") String password);
}

生成公钥和私钥

我们需要在授权中心生成真正的公钥和私钥。我们必须有一个生成公钥和私钥的secret,这个可以配置到application.yml中:

  jwt:pubKeyPath: C:\\tmp\\rsa\\rsa.pub # 公钥地址priKeyPath: C:\\tmp\\rsa\\rsa.pri # 私钥地址secret: sf3423jsdf#3$@FDS32expire: 30 # 过期时间,单位分钟cookieName: TOKEN

然后编写属性类读取jwt配置,并从秘钥配置文件中读取出响应的公钥及私钥,加载这些数据:

@Data
@Slf4j
@ConfigurationProperties(prefix = "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名称/*** @PostContruct:在构造方法执行之后执行该方法*/@PostConstructpublic 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) {log.error("初始化公钥和私钥失败!", e);throw new RuntimeException();}}
}

AuthController

编写授权接口,我们接收用户名和密码,校验成功后,写入cookie中。

  • 请求方式:post

  • 请求路径:/auth/accredit

  • 请求参数:username和password

  • 返回结果:无

代码:

@RestController
@RequestMapping("auth")
@EnableConfigurationProperties(JwtProperties.class)
public class AuthController {@Autowiredprivate AuthService authService;@Autowiredprivate JwtProperties jwtProperties;/*** 登录授权** @param username* @param password* @return*/@PostMapping("accredit")public Resp authentication(@RequestParam("username") String username,@RequestParam("password") String password,HttpServletRequest request,HttpServletResponse response) {// 登录校验String token = this.authService.authentication(username, password);if (StringUtils.isBlank(token)) {return Resp.fail("登录失败,用户名或密码错误");}// 将token写入cookie,并指定httpOnly为true,防止通过JS获取和修改CookieUtils.setCookie(request, response, jwtProperties.getCookieName(), token, jwtProperties.getExpire());return Resp.ok("登录成功");}
} 

AuthService

在auth-service:

@Service
public class AuthService {@Autowiredprivate UmsClient umsClient;@Autowiredprivate JwtProperties jwtProperties;public String authentication(String username, String password) {try {// 调用微服务,执行查询Resp resp = this.umsClient.queryUser(username, password);MemberEntity memberEntity = resp.getData();// 如果查询结果为null,则直接返回nullif (memberEntity == null) {return null;}// 如果有查询结果,则生成tokenMap map = new HashMap<>();map.put("id", memberEntity.getId());map.put("username", memberEntity.getUsername());String token = JwtUtils.generateToken(map, jwtProperties.getPrivateKey(), jwtProperties.getExpire());return token;} catch (Exception e) {e.printStackTrace();}return null;}
}

UmsClient

接下来我们肯定要对用户密码进行校验,所以我们需要通过FeignClient去访问 ums-service微服务:

在auth中引入ums-interface依赖:

com.atguiguums-interface0.0.1-SNAPSHOT

编写UmsClient:

@FeignClient("ums-service")
public interface UmsClient extends UmsApi {
}

CookieUtils

要注意,这里我们使用了一个工具类,CookieUtils,可以在课前资料中找到,我们把它添加到core中,然后引入servlet相关依赖即可:

package com.leon.core.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)// 设置域名的cookiecookie.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.cndomainName = domains[len - 3] + "." + domains[len - 2] + "." + domains[len - 1];} else if (len <= 3 && len > 1) {// xxx.com or xxx.cndomainName = domains[len - 2] + "." + domains[len - 1];} else {domainName = serverName;}}if (domainName != null && domainName.indexOf(":") > 0) {String[] ary = domainName.split("\\:");domainName = ary[0];}return domainName;}}

 


本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!

相关文章