Bootstrap

spring cloud 前后端分离集成CAS client

spring cloud 前后端分离集成CAS client

服务端搭建与简易配置

客户端集成遇到的问题

是否启用CAS (公网登录页一套、内网CAS一套)

jar包原始注解中直接引入,没有提供是否启用的属性

@EnableCasClient

通过自定义注解实现自由开关

@Configuration
@ConditionalOnProperty(name = "casqy.enabled", havingValue = "true")
@Import(CasClientConfiguration.class)
public class ConditionalCasClientConfiguration {
}
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@Import({ConditionalCasClientConfiguration.class})
public @interface CasClient {
}

cas认证过期固定重定向前端首页

CAS会转发自己系统认证失败的接口地址:
http://127.0.0.1:8080/cas/login?service=http://127.0.0.1:8087/api/auth/cn/dengl

service= 后面跟的就是在CAS认证完后会转发回来的地址,这样就会导致资源接口认证失败就成调用接口,而不是访问回应用系统,所以需要重写CAS redirect 重定向方法

@Configuration
public class CasClientConfig extends CasClientConfigurerAdapter {
	@Override
	public void configureAuthenticationFilter(FilterRegistrationBean authenticationFilter) {
		Map<String, String> initParameters = authenticationFilter.getInitParameters();
		initParameters.put("authenticationRedirectStrategyClass", "org.springblade.auth.redirect.CustomAuthRedirectStrategy");
	}

	@Override
	public void configureValidationFilter(FilterRegistrationBean filterRegistrationBean) {

	}

	@Override
	public void configureHttpServletRequestWrapperFilter(FilterRegistrationBean filterRegistrationBean) {

	}

	@Override
	public void configureAssertionThreadLocalFilter(FilterRegistrationBean filterRegistrationBean) {

	}
}
@Component
public class CustomAuthRedirectStrategy implements AuthenticationRedirectStrategy {
	@Override
	public void redirect(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, String s) throws IOException {
		StringBuilder stringBuilder = new StringBuilder();
		// 1.此处判断请求路径是否是cas/login认证接口请求,但请求报错不是(登录接口:dengl,获取token接口:skipLogin)
		// 在cas认证过期时,需要对其他资源调用接口进行限制,所以返回给前端401状态
		if(s.contains("/cas/login")&&!s.contains("dengl")&&!s.contains("skipLogin")){
			String loginUrl = s.substring(0, s.indexOf("?"));
			// 1.1 先找到第一个斜杠(通常位于 "http://" 后)
			int firstSlash = loginUrl.indexOf("/") + 2;
			// 1.2 再找到下一个斜杠,从刚才找到的斜杠后面开始
			int secondSlash = loginUrl.indexOf("/", firstSlash);
			// 1.3 如果secondSlash为-1(即之后没有其他斜杠),则截取到字符串末尾
			int thirdSlash = secondSlash != -1 ? loginUrl.indexOf("/", secondSlash + 1) : loginUrl.length();
			// 1.4 根据找到的斜杠位置截取子字符串
			String http = loginUrl.substring(0, secondSlash != -1 ? secondSlash : loginUrl.length());
			// 1.5 固定转发访问的接口地址,不固定service里会是转发的前端调用报错接口 (暂时没用)
			stringBuilder.append(loginUrl+"?service="+http+"/api/auth/cn/dengl");
			// 1.6 固定给401,让前端页面返回首页从获取token开始
			httpServletResponse.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
			httpServletResponse.setHeader("Location", stringBuilder.toString()); // 提供重定向 URL,但不自动重定向
			httpServletResponse.getWriter().write("Unauthorized - Please login at: " + stringBuilder.toString());
		}else if(s.contains("/cas/login")&&s.contains("skipLogin")) {
			stringBuilder.append(s);
			httpServletResponse.sendRedirect(stringBuilder.toString());
		}else{
			stringBuilder.append(s);
			httpServletResponse.sendRedirect(stringBuilder.toString());
		}
	}
}

博主这边应用系统前端只对登录、登出进行前端url转发。

所以在第一个if中只对应用系统资源访问接口进行判断(排除登录、登出、跳转),请求头返回 401 让前端直接去调用token的获取,这样就解决资源接口访问状态码 302 前端还要自行处理转发问题

CAS跳转前端首页,过期问题

cas过期处理

 skipLoginTwo().then(res => {
        let data = res.data.data;
        if (data===undefined) {
          window.location.href=res.request.responseURL;
        } else{
        //获取token
        }

后端处理了转发路径问题,前端直接调用就行
login、logout接口都只返回302状态码,res.data.data都是undefined,当然你也可以在请求头中加标识,前端判断

跨域问题

location /cas/ {
    add_header 'Access-Control-Allow-Origin' '*';
    add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
    add_header 'Access-Control-Allow-Headers' 'DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Authorization';
    add_header 'Access-Control-Allow-Credentials' 'true';
    proxy_pass http://ip:port;
}

全是通过自己服务器的nginx去转发

;