最近公司接了一个项目,甲方需要集成到金智系统登录,他们的数据在那边,然后需要使用cas来完成,网上了解了一下 大概就是通过cas系统来拦截请求验票,重定向到指定url登录以后再调回来处理请求接口
大致流程如下
1. 在Maven项目中引入CAS(Central Authentication Service)客户端核心库。CAS是一个开源的企业级单点登录解决方案,用于实现Web应用程序的集中认证和授权。
org.jasig.cas.clientcas-client-core3.5.0
2.yml配置cas
3.cas配置类
@Configuration @Slf4j @ConditionalOnProperty(value = "cas.loginType", havingValue = "cas") public class CasFilterConfig { /** * 需要走cas拦截的地址(/* 所有地址都拦截) */ @Value("${cas.urlPattern:/*}") private String filterUrl; /** * 默认的cas地址,防止通过 配置信息获取不到 */ @Value("${cas.server-url-prefix}") private String casServerUrl; /** * 应用访问地址(这个地址需要在cas服务端进行配置) */ @Value("${cas.authentication-url}") private String authenticationUrl; /** * 应用访问地址(这个地址需要在cas服务端进行配置) */ @Value("${cas.client-host-url}") private String appServerUrl; @Bean public ServletListenerRegistrationBean servletListenerRegistrationBean() { log.info(" n cas 单点登录配置 n appServerUrl = " + appServerUrl + "n casServerUrl = " + casServerUrl); log.info(" servletListenerRegistrationBean "); ServletListenerRegistrationBean listenerRegistrationBean = new ServletListenerRegistrationBean(); listenerRegistrationBean.setListener(new SingleSignOutHttpSessionListener()); listenerRegistrationBean.setOrder(Ordered.HIGHEST_PRECEDENCE); return listenerRegistrationBean; } /** * 单点登录退出 * * @return */ @Bean public FilterRegistrationBean singleSignOutFilter() { log.info(" servletListenerRegistrationBean "); FilterRegistrationBean registrationBean = new FilterRegistrationBean(); registrationBean.setFilter(new SingleSignOutFilter()); registrationBean.addUrlPatterns(filterUrl); registrationBean.addInitParameter("casServerUrlPrefix", casServerUrl); registrationBean.setName("CAS Single Sign Out Filter"); registrationBean.setOrder(1); return registrationBean; } /** * 单点登录认证 * * @return */ @Bean public FilterRegistrationBean AuthenticationFilter() { log.info(" AuthenticationFilter "); FilterRegistrationBean registrationBean = new FilterRegistrationBean(); registrationBean.setFilter(new AuthenticationFilter()); registrationBean.addUrlPatterns(filterUrl); registrationBean.setName("CAS Filter"); registrationBean.addInitParameter("casServerLoginUrl", casServerUrl); registrationBean.addInitParameter("serverName", appServerUrl); registrationBean.setOrder(1); return registrationBean; } /** * 单点登录校验 * * @return */ @Bean public FilterRegistrationBean Cas30ProxyReceivingTicketValidationFilter() { log.info(" Cas30ProxyReceivingTicketValidationFilter "); FilterRegistrationBean registrationBean = new FilterRegistrationBean(); registrationBean.setFilter(new Cas30ProxyReceivingTicketValidationFilter()); registrationBean.addUrlPatterns(filterUrl); registrationBean.setName("CAS Validation Filter"); registrationBean.addInitParameter("casServerUrlPrefix", authenticationUrl); registrationBean.addInitParameter("serverName", appServerUrl); registrationBean.setOrder(1); return registrationBean; } /** * 单点登录请求包装 * * @return */ @Bean public FilterRegistrationBean httpServletRequestWrapperFilter() { log.info(" httpServletRequestWrapperFilter "); FilterRegistrationBean registrationBean = new FilterRegistrationBean(); registrationBean.setFilter(new HttpServletRequestWrapperFilter()); registrationBean.addUrlPatterns(filterUrl); registrationBean.setName("CAS HttpServletRequest Wrapper Filter"); registrationBean.setOrder(1); return registrationBean; } }
4.对接cas统一认证后接受的用户信息对象
/** * @Author: * @Date: * @Description: 使用cas对接封装的cas返回的用户信息的对象 */ public class CasUtil { private static final Logger LOGGER = LoggerFactory.getLogger(CasUtil.class); /** * cas client 默认的session key */ public final static String CAS = "_const_cas_assertion_"; /** * 封装CasUserInfo * * @param request * @return */ public static CasUserInfo getCasUserInfoFromCas(HttpServletRequest request) { Object object = request.getSession().getAttribute(CAS); if (null == object) { return null; } Assertion assertion = (Assertion) object; return buildCasUserInfoByCas(assertion); } /** * 构建CasUserInfo * * @param assertion * @return */ private static CasUserInfo buildCasUserInfoByCas(Assertion assertion) { if (null == assertion) { LOGGER.error(" Cas没有获取到用户 "); return null; } CasUserInfo casUserInfo = new CasUserInfo(); String userName = assertion.getPrincipal().getName(); LOGGER.info(" cas对接登录用户= " + userName); casUserInfo.setUserAccount(userName); //获取属性值 Map attributes = assertion.getPrincipal().getAttributes(); Object name = attributes.get("cn"); casUserInfo.setUserName(name == null ? userName : name.toString()); casUserInfo.setAttributes(attributes); return casUserInfo; }
5.用户信息实体
/** * @Author: * @Date: * @Description: 返回的用户信息 */ @Setter @Getter public class CasUserInfo { /** 用户名 */ private String userName; /** 用户 */ private String userAccount; /** 用户信息 */ private Map attributes; }
6.验证统一认证登录后跳回来的处理
/** * 统一认证成功后跳转 * * @return */ @GetMapping(value = "/index") public ResponseVo index(HttpServletRequest request) { CasUserInfo userInfo = CasUtil.getCasUserInfoFromCas(request); log.info("userInfo = " + JSONObject.toJSON(userInfo)); }
统一认证登录成功以后,回来再根据用户信息校验用户,生成对应token
7.退出
/** * 统一退出接口 * * @return */ @GetMapping(value = "/logout") public RedirectView logout(HttpServletRequest request) { // 清理缓存 // return "redirect:https://********/logout"; cas的退出 return new RedirectView("https://************/logout"); }
最后跳转回来的时候因为url里面带了;被拦截报错
The request was rejected because the URL contained a potentially malicious String “;”
最后在网上搜了一下相关错误
解决办法 在yml配置server加了以下配置
servlet: session: tracking-modes: cookie
到此这篇关于springboot前后端分离集成CAS单点登录(统一认证)的文章就介绍到这了,更多相关springboot CAS单点登录内容请搜索IT俱乐部以前的文章或继续浏览下面的相关文章希望大家以后多多支持IT俱乐部!