EAS登录集成Oauth2.0的开发指导文档
背景
EAS默认采用CAS作为EAS本身的统一认证中心,由于CAS版本比较老旧,因此标准不支持Oauth2.0协议,由于OAuth2.0的普遍使用性,本文旨在简化EAS对接Oauth2.0过程中的流程,适用于EAS全版本
EAS目前登录流程
登录拦截器配置
二次扩展
二开扩展遵循少改代码,不影响标准产品,不被打补丁影响功能,改动多意味着容易出错,后续打补丁很大概率功能会被冲掉,尤其是修改了很多配置文件,因此为了不受补丁影响,最好是将所有功能全部集成到私包代码里面,通过反编译工具(最好是使用luyten反编译工具来反编译,EAS8.8版本以下可以直接使用附录源码)修改
com.kingdee.bos.sso.client.filter.authentication.KDPortalAuthenticationFilter和
com.kingdee.bos.sso.client.filter.validation.KDPortalTicketValidationFilter两个类改动最小,无需修改web.xml来添加自定义拦截器
第一步:拦截跳转,未登录情况需跳转到oauth2.0的统一认证中心登录界面
代码修改:需要在KDPortalAuthenticationFilter doFilter方法调用super.doFilter之前嵌入逻辑
String url= "http://cas.example.org:8080/cas/oauth2.0/authorize?"+
"response_type=code&client_id=100001&redirect_uri="
+URLEncoder.encode(request.getRequestURL().toString(),"utf-8");
//设置跳转地址
this.setCasServerLoginUrl(url);
//设置code为登录票据标识,不拦截
String code = request.getParameter("code");
String ticket = request.getParameter("ticket");
if(!StringUtil.isEmpty(code)){
this.setArtifactParameterName("code");
}else if(!StringUtil.isEmpty(ticket)){
this.setArtifactParameterName("ticket");
}
String valiDataUrl = "http://cas.example.org:8080/cas/oauth2.0/accessToken?grant_type=authorization_code&client_id=100001&client_secret=100001" +
"&code="+code+"&redirect_uri=http://127.0.0.1:56898/portal/";
//通过url获取用户信息
//String user = HttpClient.getUserInfo(valiDataUrl);
String user = "user";
//可以放账套信息和语言信息等登录需要的信息,如果不放需要在CASLoginConfig.properties配置
Map<String,Object> map = new HashMap<String,Object>();
map.put("solutionName","eas");
map.put("dataCenter","SP1DEMO");
map.put("locale","L2");
map.put("dbType","0");
map.put("userAuthPattern","eas");
map.put("isPureWeb","true");
map.put("loginFlow","true");
map.put("sso.user.mapping","true");
Assertion assertion = new AssertionImpl(new AttributePrincipalImpl(user, map));
return assertion;
采用此方案集成后,三方系统对接 index2sso.jsp 的方式失效
原因:index2sso.jsp最后跳转loginCheck.action请求是依赖于传统cas的方式来实现登录,本质上走的还是eas的登录逻辑,因为对接三方系统后,强制使用了 this.setCasServerLoginUrl(url)代码来设置跳转到oauth2.0的认证中心,导致此方法跳转不到传统eas的登录地址,该功能失效
url参数为跳转认证中心登录地址(三方提供),第7,8行代码是为了处理登录票据标识,ticket是cas的默认标识,code是oauth2.0的标识,基本上无需改动。如果需要保留eas本身登录,不能屏蔽对ticket的处理,如果无需保留eas的登录,则可以不对ticket进行处理,只需要处理code即可
第二步:通过code进行系统登录
统一认证中心登录成功后会发送302跳转请求到eas,并携带code到eas,eas需要校验code的合法性,以及从code换取用户的登录信息然后进行登录,我们需要将这一步要转到我们自己的类中来
代码修改:需要修改KDPortalTicketValidationFilter类的getTicketValidator方法在第一行添加
if("code".equals(type))
return new OAuth20CodeValidata();
并修改preFilter方法,在前面添加
String code = servletRequest.getParameter("code");
String type = "ticket";
if(!StringUtil.isEmpty(code)){
type ="code";
}
这样就将oauth2.0的回调校验转到OAuth20CodeValidata类
第三步:OAuth20CodeValidata类校验
OAuth20CodeValidata需要实现org.jasig.cas.client.validation.TicketValidator接口,覆写方法
public Assertion validate(String code, String url);
我们只需要code参数换取合法用户信息即可,伪代码如下:
根据现场实际情况校验code,并传递dataCenter和dbType参数,其它参数不用修改,写死即可。
4.常见问题
用户映射:在认证中心登录用的是张三,在EAS对应的用户编码是张三1,这种场景需要在OAuth20CodeValidata类中自行处理映射,EAS本身也提供了一个表(T_SSO_External2EasUsers)来维护这种映射关系,对应的接口是External2EasUsersFacadeControllerBean来处理,如果有需要可以使用改接口维护映射关系
5.附录
文档样例源码,可以直接使用
6.问题
修改:如果需要支持,则需要将此请求保持原有逻辑,增加此请求的
String path= request.getServletPath();
String password = request.getParameter("password");
//较新补丁的环境password被替换为kdacctoken
String kdacctoken= request.getParameter("kdacctoken");
boolean flag = false;
if("/web_frame/easrpc/loginCheck.action".equals(path) && (!StringUtil.isEmpty(password)||
!StringUtil.isEmpty(kdacctoken))){
flag =true;
}
if(!flag){
this.setCasServerLoginUrl(url);//flag=true,才第一步的第5行,否则保持原有逻辑,不处理跳转地址
}
EAS登录集成Oauth2.0的开发指导文档
本文2024-09-22 20:08:27发表“eas cloud知识”栏目。
本文链接:https://wenku.my7c.com/article/kingdee-eas-111712.html