一:配置文件
auth:
tokenValiditySeconds: 1200 #token存储到redis的过期时间
clientId: XcWebApp
clientSecret: XcWebApp
cookieDomain: xuecheng.com
cookieMaxAge: -1
二:配置类
日后再写!
三:业务代码
一:代码
@Service
public class AuthService {
@Autowired
private RestTemplate restTemplate;
@Autowired
private LoadBalancerClient loadBalancerClient;
@Autowired
private StringRedisTemplate redisTemplate;
@Value("${auth.tokenValiditySeconds}")
private long ttl;
/**
* 用户认证获取令牌并存储到redis
* @author : yechaoze
* @date : 2019/7/25 12:28
* @param username :
* @param password :
* @param clientId :
* @param clientSecret :
* @return : com.xuecheng.framework.domain.ucenter.ext.AuthToken
*/
public AuthToken login(String username, String password, String clientId, String clientSecret) {
//请求SpringSecurity获取了令牌
AuthToken authToken = this.getAuthToken(username, password, clientId, clientSecret);
if (authToken==null){
ExceptionCast.cast(AuthCode.AUTH_LOGIN_APPLYTOKEN_FAIL);
}
//将token存储到redis
//令牌
String access_token = authToken.getAccess_token();
//内容
String content = JSON.toJSONString(authToken);
boolean token = this.saveToken(access_token, content, ttl);
if (!token){
ExceptionCast.cast(AuthCode.AUTH_LOGIN_TOKEN_SAVEFAIL);
}
return authToken;
}
/**
* 将token存储到redis
* @author : yechaoze
* @date : 2019/7/25 13:21
* @param access_token :令牌
* @param content : AuthToken对象的内容
* @param ttl :过期时间
* @return : boolean
*/
private boolean saveToken(String access_token,String content,long ttl){
String key="user_token:"+access_token;
redisTemplate.boundValueOps(key).set(content,ttl,TimeUnit.SECONDS);
Long expire = redisTemplate.getExpire(key,TimeUnit.SECONDS);
return expire>0;
}
/**
* 获取令牌
* @author : yechaoze
* @date : 2019/7/25 13:06
* @param username :
* @param password :
* @param clientId :
* @param clientSecret :
* @return : java.util.Map
*/
private AuthToken getAuthToken(String username, String password, String clientId, String clientSecret){
//远程调用获取uri地址
ServiceInstance serviceInstance = loadBalancerClient.choose(XcServiceList.XC_SERVICE_UCENTER_AUTH);
URI uri = serviceInstance.getUri();
String authUrl=uri+"/auth/oauth/token";
//设置headers
LinkedMultiValueMap<String,String> headers=new LinkedMultiValueMap<>();
String httpBasic = this.getHttpBasic(clientId, clientSecret);
headers.add("Authorization", httpBasic);
//设置body
LinkedMultiValueMap<String,String> body=new LinkedMultiValueMap<>();
body.add("grant_type","password");
body.add("username",username);
body.add("password",password);
HttpEntity<MultiValueMap<String, String>> httpEntity=new HttpEntity<>(body,headers);
//指定 restTemplate当遇到400或401响应时候也不要抛出异常,也要正常返回值
restTemplate.setErrorHandler(new DefaultResponseErrorHandler(){
@Override
public void handleError(ClientHttpResponse response) throws IOException {
//当响应的值为400或401时候也要正常响应,不要抛出异常
if(response.getRawStatusCode()!=400 && response.getRawStatusCode()!=401){
super.handleError(response);
}
}
});
ResponseEntity<Map> exchange = restTemplate.exchange(authUrl, HttpMethod.POST, httpEntity, Map.class);
Map jwtBody = exchange.getBody();
if (jwtBody == null|| jwtBody.get("access_token")==null|| jwtBody.get("refresh_token")==null|| jwtBody.get("jti")==null){
return null;
}
AuthToken authToken=new AuthToken();
authToken.setAccess_token((String) jwtBody.get("jti"));//用户身份令牌
authToken.setJwt_token((String) jwtBody.get("access_token"));//jwt令牌
authToken.setRefresh_token((String) jwtBody.get("refresh_token"));//刷新令牌
return authToken;
}
/**
* 获取httpBasic
* @author : yechaoze
* @date : 2019/7/25 12:31
* @param clientId :
* @param clientSecret :
* @return : java.lang.String 返回格式 Basic xxxxxxxxxxxxxxxxxx
*/
private String getHttpBasic(String clientId, String clientSecret){
String string=clientId+":"+clientSecret;
byte[] bytes = Base64Utils.encode(string.getBytes());
return "Basic "+new String(bytes);
}
}
二:代码解释
- getHttpBasic
使用配置文件中的clientId,clientSecret获取返回格式为Basic xxxxxxxxxx的数据
- getAuthToken
先远程调用获取uri,拼接url,设置headers和body,使用restTemplate.exchang
说明:1)url: 请求地址;
2)method: 请求类型(如:POST,PUT,DELETE,GET);
3)requestEntity: 请求实体,封装请求头,请求内容
4)responseType: 响应类型,根据服务接口的返回类型决定
5)uriVariables: url中参数变量值
- saveToken
access_token:令牌
content:AuthToken对象的内容
ttl:超时时间
- login
调用getAuthToken方法及saveToken方法
四:Controller的实现
一:代码
import javax.servlet.http.HttpServletResponse;
@RestController
@RequestMapping("/")
public class AuthController implements AuthControllerApi {
@Autowired
private AuthService authService;
@Value("${auth.clientId}")
private String clientId;
@Value("${auth.clientSecret}")
private String clientSecret;
@Value("${auth.cookieDomain}")
private String domain;
@Value("${auth.cookieMaxAge}")
private int cookieMaxAge;
@Override
@PostMapping("/userLogin")
public LoginResult login(LoginRequest loginRequest) {
if (loginRequest==null|| StringUtils.isEmpty(loginRequest.getUsername())){
ExceptionCast.cast(AuthCode.AUTH_USERNAME_NONE);
}
if (loginRequest==null|| StringUtils.isEmpty(loginRequest.getPassword())){
ExceptionCast.cast(AuthCode.AUTH_PASSWORD_NONE);
}
String username = loginRequest.getUsername();
String password = loginRequest.getPassword();
AuthToken authToken= authService.login(username,password,clientId,clientSecret);
//将令牌存储到cookie
String access_token = authToken.getAccess_token();
this.saveCookie(access_token);
return new LoginResult(CommonCode.SUCCESS,access_token);
}
/**
* 存储cookie
* @author : yechaoze
* @date : 2019/7/25 13:51
* @param token :
* @return : void
*/
private void saveCookie(String token){
//HttpServletResponse response,String domain,String path,String name,String value,int maxAge,boolean httpOnly
HttpServletResponse response = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getResponse();
CookieUtil.addCookie(response,domain,"/","uid",token,cookieMaxAge,false);
}
@Override
public ResponseResult logout() {
return null;
}
}
二:代码解释
- saveCookie
使用cookieUtils把cookie存入在xuecheng.com域名中
- login
调用service中的login方法,并调用saveCookie实现将cookie存入xuecheng.com 将access_token,refresh_token,jti存入redis
三:结果



五:总结
写的有点乱,过几天重新整理一下
Comments | 2 条评论
学习了
@快云