package cn.mb.cloud.auth.service; import cn.mb.cloud.auth.config.SecurityEnum; import cn.mb.cloud.auth.entity.User; import cn.mb.cloud.auth.util.JWTTokenUtil; import cn.mb.cloud.auth.util.RedisUtil; import cn.mb.cloud.auth.util.TokenException; import cn.mb.cloud.auth.util.httpClinet.HttpClientUtil; import cn.mb.cloud.auth.util.httpClinet.HttpResult; import cn.mb.cloud.auth.warpper.*; import com.alibaba.fastjson.JSON; import org.apache.commons.lang3.ObjectUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.security.core.authority.AuthorityUtils; import org.springframework.security.core.userdetails.UserDetails; import org.springframework.security.core.userdetails.UsernameNotFoundException; import org.springframework.security.crypto.password.PasswordEncoder; import org.springframework.stereotype.Service; import java.util.Base64; import java.util.HashMap; import java.util.Map; @Service public class UserDetailsServiceImpl implements IUserDetailsService { @Autowired private PasswordEncoder passwordEncoder; @Autowired private HttpClientUtil httpClientUtil; @Autowired private RedisUtil redisUtil; private final String password = "LEM5yk92jfi!0mjDzRXF"; @Value("${token.uri}") private String uri; @Override public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException { String pass = passwordEncoder.encode(password); User user = new User(username, pass, AuthorityUtils.commaSeparatedStringToAuthorityList("admin")); return user; } /** * 获取身份凭证 * @param request * @return * @throws Exception */ @Override public TokenResponse getToken(GetTokenRequest request) throws Exception { TokenResponse tokenResponse = new TokenResponse(); Map params = new HashMap<>(); params.put("grant_type", SecurityEnum.password); params.put("username", request.getUsername()); params.put("password", password); params.put("scope", "all"); Map header = new HashMap<>(); String string = Base64.getEncoder().encodeToString("1Oy7OUJwHn4T1uSA:JvAdJCdqDCzKf1zZ".getBytes("UTF-8")); header.put("Authorization", "Basic " + string); HttpResult httpResult = httpClientUtil.pushHttpRequset("POST", uri + "/oauth/token", params, header, "form"); if(httpResult.getCode() == 200){ OauthToken oauthToken = JSON.parseObject(httpResult.getData(), OauthToken.class); tokenResponse.setToken(oauthToken.getAccess_token()); tokenResponse.setRefresh_token(oauthToken.getRefresh_token()); tokenResponse.setExpiration_time(oauthToken.getExpires_in()); //缓存进redis saveAuthTokenToRedis(request, oauthToken); } return tokenResponse; } /** * 存储token信息到redis * @param request * @param oauthToken */ public void saveAuthTokenToRedis(GetTokenRequest request, OauthToken oauthToken) { delRedisToken(request.getUsername()); String access_token = oauthToken.getAccess_token(); String key = access_token.substring(access_token.length() - 32); redisUtil.setStrValue(key, request.getUsername(), SecurityEnum.token_effective_time); redisUtil.setStrValue(request.getUsername(), JSON.toJSONString(request.getObject())); redisUtil.setStrValue(request.getUsername() + ":auth-token", oauthToken.getAccess_token()); String refresh_token = oauthToken.getRefresh_token(); key = refresh_token.substring(refresh_token.length() - 32); redisUtil.setStrValue(key, request.getUsername(), SecurityEnum.refresh_token_effective_time); redisUtil.setStrValue(request.getUsername() + ":refresh-auth-token", oauthToken.getAccess_token()); } /** * 删除redis中的无效数据 * @param username */ public void delRedisToken(String username){ String token = redisUtil.getValue(username + ":auth-token"); if(ObjectUtils.isNotEmpty(token)){ String key = token.substring(token.length() - 32); redisUtil.remove(key); } String refresh_token = redisUtil.getValue(username + ":refresh-auth-token"); if(ObjectUtils.isNotEmpty(refresh_token)){ String key = refresh_token.substring(refresh_token.length() - 32); redisUtil.remove(key); } } /** * 刷新token * @param request * @return * @throws Exception */ @Override public TokenResponse refreshToken(RefreshTokenRequest request) throws Exception { String user_name = null; try { ParseToken parseToken = JWTTokenUtil.parseToken(request.getToken()); user_name = parseToken.getUser_name(); }catch (TokenException e){ if(e.getCode() == 10003){//token过期,通过刷新凭证在缓存中获取用户名 String refresh_token = request.getRefresh_token(); String key = refresh_token.substring(refresh_token.length() - 32); user_name = redisUtil.getValue(key); }else{ throw e; } } if(ObjectUtils.isEmpty(user_name)){ return null; } String obj = redisUtil.getValue(user_name); TokenResponse tokenResponse = new TokenResponse(); Map params = new HashMap<>(); params.put("refresh_token", request.getRefresh_token()); params.put("grant_type", SecurityEnum.refresh_token); Map header = new HashMap<>(); String string = Base64.getEncoder().encodeToString("1Oy7OUJwHn4T1uSA:JvAdJCdqDCzKf1zZ".getBytes("UTF-8")); header.put("Authorization", "Basic " + string); HttpResult httpResult = httpClientUtil.pushHttpRequset("POST", uri + "/oauth/token", params, header, "form"); if(httpResult.getCode() == 200){ OauthToken oauthToken = JSON.parseObject(httpResult.getData(), OauthToken.class); tokenResponse.setToken(oauthToken.getAccess_token()); tokenResponse.setRefresh_token(oauthToken.getRefresh_token()); tokenResponse.setExpiration_time(oauthToken.getExpires_in()); //缓存进redis saveAuthTokenToRedis(user_name, obj, oauthToken); } return tokenResponse; } /** * 保存缓存 * @param user_name * @param obj * @param oauthToken */ public void saveAuthTokenToRedis(String user_name, String obj, OauthToken oauthToken) { delRedisToken(user_name); String access_token = oauthToken.getAccess_token(); String key = access_token.substring(access_token.length() - 32); redisUtil.setStrValue(key, user_name, SecurityEnum.token_effective_time); redisUtil.setStrValue(user_name, obj); redisUtil.setStrValue(user_name + ":auth-token", oauthToken.getAccess_token()); String refresh_token = oauthToken.getRefresh_token(); key = refresh_token.substring(refresh_token.length() - 32); redisUtil.setStrValue(key, user_name, SecurityEnum.refresh_token_effective_time); redisUtil.setStrValue(user_name + ":refresh-auth-token", oauthToken.getAccess_token()); } }