yiqing期间是否你也准备着无数的面试**是的I am keepping interviewed**
上周电话面试了某B公司,印象最深的还是那个单点登录的问题,毕竟很多底层的问题以后再分享,比如聊聊AQS等,不过这节先谈谈SSO,毕竟老生常谈的东西,再次复习一下,表示对Apache的shiro的复习。
- JwtBuilder
这个接口是shiro单点登录的核心部分,比如设置了Subject,过期时间以及claim等,而返回的token就是通过String jws =jwtBuilder.compact();
贴一部分代码
public static String createToken(String oaOwnerUserId,String url,Map<String,Object> otherParam) {
try {
JwtBuilder jwtBuilder = Jwts.builder()
.setSubject("oa 代办")
.setIssuer(oaOwnerUserId)
.setExpiration(DateUtils.addDays(new Date(), 60))
.setIssuedAt(new Date())
.setId(UUID.randomUUID().toString())
.claim("redirect_url", url)
.signWith(key);
if(otherParam !=null && !otherParam.isEmpty()) {
for(Map.Entry<String, Object> entry : otherParam.entrySet()) {
jwtBuilder.claim(entry.getKey(), entry.getValue());
}
}
String jws =jwtBuilder.compact();
return Base64.getUrlEncoder().encodeToString(jws.getBytes());
}catch(Exception e) {
e.printStackTrace();
return null;
}
}
当然跟这个方法配套使用的就是解码校验的方法 ,也是比较简单
public static AjaxResult< Map<String, Object>> verifyToken(String token) {
try {
String decoderToken = new String (Base64.getUrlDecoder().decode(token));
Jws<Claims> claims = Jwts.parserBuilder().setSigningKey(key).build().parseClaimsJws(decoderToken);
String oaOwnerUserId = claims.getBody().getIssuer();
return AjaxResult.ok().put("redirect_url", claims.getBody().get("redirect_url"))
.put("userId", oaOwnerUserId);
}catch(Exception e) {
e.printStackTrace();
return AjaxResult.error(AjaxResult.ERR_AUTHORIZE_ERROR, "oa代办登陆失效");
}
}
基本上提供加密以及解码的方法提供了,然后往下就是在移动端或者PC端进行调用处理
- Subject
这是shiro里面的主体获取是需用他提供的工具类
Subject subject = SecurityUtils.getSubject();
//生成一个token
String token = TokenGenerator.generateValue();
super.subjectMap.put(token,subject);
if(subject!=null){
OAuth2Token auth2Token = new OAuth2Token(token);
auth2Token.setPassword(loginAsk.getPassword());
auth2Token.setUserName(loginAsk.getName());
subject.login(auth2Token);
logger.info("==>subject :"+subject);
}
通过这一块的代码就可以明确的了解到生成的token以及需要从oauth到token的转换过程是需要OAuth2Token继承org.apache.shiro.authc.AuthenticationToken,从而可以重写方法
@Override
public String getPrincipal() {
return token;
}
@Override
public Object getCredentials() {
return token;
}
获取到了token以及Subject之后就可以处理对应的数据库IO操作进行校验
if(!subject.isAuthenticated()){
//记录登录失败日志
}
整个过程核心的部分都大概介绍了,主要还是需要对shiro的角色校验以及权限校验的代码进行debug进去才看清楚这个框架为什么有这样的写法,优缺点是什么。因此这里为了更全面的了解整个SSO的流程这里有一篇推荐文章