认证和SSO(四)

认证和SSO(四)

1、access_token的有效期

我们知道 token的有效期,是控制登陆一次能访问多长时间微服务。那么access_token一般设置多长时间比较好呢?因为有access_token可以直接访问微服务,而不需要再次认证,所以access_token不建议设置很长的有效期,一般为一到两个小时,因为access_token一旦泄漏,风险很高。但是这样又会有一个问题,access_token过期了,而session没有过期,这样会导致,我们还是登陆的状态,但是无法访问微服务了。

将access_toen过期时间设置为10s,后访问如下

2、OAuth2的refresh_token

为了解决access_token过期的问题,OAuth2协议为我们提供了refresh_token。我们在配置支持refresh_token后,在通过密码模式和授权码模式获取access_token的同时,也会发给我们一个refresh_token。在当access_token过期后,客户端应用可以拿着refresh_token和clientId、clientSecret去授权服务器获取新的access_token,在这个过程中不需要用户再次输入用户名和密码。因为refresh_token要配合clientId、clientSecret一起使用才有效,所以就算泄漏了refresh_token也不要紧,保护好clientSecret就好了。因此refresh_token可以设置较长的时间,一般与认证服务器session过期时间设置一致即可。

3、配置项目支持refresh_token

3.1、配置授权服务器支持refresh_token

3.1.1、数据库配置authorized_grant_types添加refresh_token,refresh_token_validity设置refresh_token过期时间,在使用密码或授权码模式申请令牌是refresh_token会一起返回

配置完成后,通过http请求工具,测试获取令牌中已经存在refresh_token

3.1.2、OAuth2认证服务器配置类的public void configure(AuthorizationServerEndpointsConfigurer endpoints)要配置userDetailsService,因为刷新令牌没有密码只有用户名。

/**

* 配置授权服务器终端的非安全特征

* authenticationManager 校验用户信息是否合法

* tokenStore:token存储

* userDetailsService:配合刷新令牌使用

*/

@Override

public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {

endpoints.authenticationManager(authenticationManager).tokenStore(new JdbcTokenStore(dataSource))

.userDetailsService(userDetailsService);

}

3.2、客户端应用改造access_token过期时,可以刷新令牌

SessionTokenFilter中获取出token是要判断access_token是否过期,过期执行刷新令牌操作

/**

* 将session中的token取出放到请求头中

*

* @author caofanqi

* @date 2020/2/6 0:34

*/

@Slf4j

@Component

public class SessionTokenFilter extends ZuulFilter {

private RestTemplate restTemplate = new RestTemplate();

@Override

public String filterType() {

return "pre";

}

@Override

public int filterOrder() {

return 0;

}

@Override

public boolean shouldFilter() {

return true;

}

@Override

public Object run() throws ZuulException {

RequestContext requestContext = RequestContext.getCurrentContext();

HttpServletRequest request = requestContext.getRequest();

TokenInfoDTO token = (TokenInfoDTO) request.getSession().getAttribute("token");

if (token != null) {

String accessToken = token.getAccess_token();

//判断access_token是否过期,需要刷新令牌

if (token.isExpires()){

String oauthTokenUrl = "http://gateway.caofanqi.cn:9010/token/oauth/token";

HttpHeaders headers = new HttpHeaders();

headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);

headers.setBasicAuth("webApp", "123456");

MultiValueMap params = new LinkedMultiValueMap<>();

params.set("grant_type", "refresh_token");

params.set("refresh_token", token.getRefresh_token());

HttpEntity> httpEntity = new HttpEntity<>(params, headers);

ResponseEntity refreshTokenResult = restTemplate.exchange(oauthTokenUrl, HttpMethod.POST, httpEntity, TokenInfoDTO.class);

request.getSession().setAttribute("token", refreshTokenResult.getBody().init());

accessToken = refreshTokenResult.getBody().getAccess_token();

log.info("refresh_token......");

}

requestContext.addZuulRequestHeader("Authorization","bearer " + accessToken);

}

return null;

}

}

启动个项目,测试

4、refresh_token过期了怎么办

虽然refresh_token的有效期比较长,但还是会过期的。如果refresh_token也过期了怎么处理呢?下面提供两种方案,具体使用那种,根据需求来决定。

4.1、refresh_token过期了,不管session过没过期,强制退出,从新输用户名密码进行认证。

4.1.1、修改SessionTokenFilter,刷新token失败后,返回错误信息供页面处理

4.1.2、修改index.html,获取异常,如果是token刷新失败,直接退出登陆

//拦截全局错误响应 ,使用方法https://www.runoob.com/jquery/ajax-ajaxerror.html

$(document).ajaxError(function(event, jqXHR, options, errorMsg) {

//jqXHR打印如下 alert(JSON.stringify(jqXHR));

//{"readyState":4,"responseText":"{\"message\":\"refresh fail\"}","responseJSON":{"message":"token refresh fail"},"status":500,"statusText":"error"}

if (jqXHR.status == 500 && jqXHR.responseJSON.message == 'token refresh fail') {

alert("登陆信息以失效");

//方案1、退出,重新登陆,走认证流程

logout();

});

4.2、refresh_token过期了,到认证服务器重新认证,如果session没过期,直接返回一个token回来;如果session过期了,重新输入用户名密码认证。

//拦截全局错误响应 ,使用方法https://www.runoob.com/jquery/ajax-ajaxerror.html

$(document).ajaxError(function(event, jqXHR, options, errorMsg) {

//jqXHR打印如下 alert(JSON.stringify(jqXHR));

//{"readyState":4,"responseText":"{\"message\":\"refresh fail\"}","responseJSON":{"message":"token refresh fail"},"status":500,"statusText":"error"}

if (jqXHR.status == 500 && jqXHR.responseJSON.message == 'token refresh fail') {

alert("登陆信息以失效");

//方案1、退出,重新登陆,走认证流程

//logout();

//方案2、去认证服务器认证

location.href = "http://auth.caofanqi.cn:9020/oauth/authorize?" +

"client_id=webApp&" +

"redirect_uri=http://web.caofanqi.cn:9000/oauth/callback&" +

"response_type=code&" +

"state=abc";

}

});

5、基于session的SSO的优缺点及适用场景

5.1、优点

安全:所有的token信息都是存放在session中,在浏览器里只有一个JSESSIONID,只要做好防session固定攻击,一般不会有什么风险。

可控性高:token和session存在了数据库,可控性较高。

跨域:客户端应用部署在哪个域名下,都可以直接跟认证服务器交互。

5.2、缺点

复杂度高:各种过期时间较多,两个session(客户端和认证服务器),两个token(access_token、refresh_token),必须请求每个东西是干什么的,过期后对系统会产生什么样的行为,怎么进行处理,都要清楚。

性能低:session、token的存取都会占用服务器资源,用户量很大的情况下,会产生各种问题。

5.3、适用场景

系统用户百万以下(token表的性能可以得到保证)。

多个开发团队开发多个客户端,每个客户端单独部署并且页面风格相同(各个系统可以跳来跳去,后面是一个统一的认证服务器,通过网关来访问微服务)。

项目源码:https://github.com/caofanqi/study-security/tree/dev-web-sso-session2

相关阅读

灵芪红胶囊价格,灵芪红胶囊多少钱一盒
365bet官网赌场

灵芪红胶囊价格,灵芪红胶囊多少钱一盒

🕒 08-18 👁️‍🗨️ 2790
最全面的PK 三星S8/S8+/S7/S7 edge对比
365bet官网赌场

最全面的PK 三星S8/S8+/S7/S7 edge对比

🕒 08-21 👁️‍🗨️ 7977
excel数字下拉数字递增怎么设置
365bet官网赌场

excel数字下拉数字递增怎么设置

🕒 07-13 👁️‍🗨️ 3546
微信链接如何制作?微信链接制作方法分享
久发365电子游戏网址多少

微信链接如何制作?微信链接制作方法分享

🕒 08-20 👁️‍🗨️ 4103
饥荒手游如何快速建造围墙 饥荒手游快速建一排墙技巧方法分享
久发365电子游戏网址多少

饥荒手游如何快速建造围墙 饥荒手游快速建一排墙技巧方法分享

🕒 08-13 👁️‍🗨️ 5984
电商平台常见的10大促销活动
365bet官网赌场

电商平台常见的10大促销活动

🕒 07-04 👁️‍🗨️ 3833
天龙八部飘渺峰的BOSS李秋水,要怎样躲她的绝技?(天龙八部缥缈峰李秋水攻略)
2024年十大免费开源网页抓取工具
365bet官网赌场

2024年十大免费开源网页抓取工具

🕒 08-01 👁️‍🗨️ 7763
王者禁赛时间怎么计算
365bet官网赌场

王者禁赛时间怎么计算

🕒 08-14 👁️‍🗨️ 8905