springboot整合CAS单点登录

 

感谢文章:https://blog.csdn.net/qq_34021712/article/details/81508273

一边写一边慢慢优化

 <!--cas的客户端 -->
        <dependency>
            <groupId>net.unicon.cas</groupId>
            <artifactId>cas-client-autoconfig-support</artifactId>
            <version>1.4.0-GA</version>
        </dependency>

 yml文件添加信息

#cas config
    cas:
        server-name: http://localhost:8083
        validate-filters: /*
        sign-out-filters: /logout
        cas-server-url-prefix: http://localhost:8080/sso
        use-session: true
        redirect-after-validation: true
        auth-filters: /*
        request-wrapper-filters: /*
        cas-server-login-url: http://localhost:8080/sso/login
        assertion-filters: /*
        logout-server-name: http://localhost:8083

上一段配置对应着实体类

/**
 * 读取cas配置文件
 * @author zhangyh
 * 2019/10/15
 */
@Component
@ConfigurationProperties(prefix = "spring.cas")
public class SpringCasAutoconfig {

    private static final Logger LOGGER = LoggerFactory.getLogger(SpringCasAutoconfig.class);
    private static final String SEPARATOR = ",";
    private String validateFilters;
    private String signOutFilters;
    private String authFilters;
    private String assertionFilters;
    private String reqWrapperFilters;
    private String casServerUrlPrefix;
    private String casServerLoginUrl;
    private String serverName;
    private String logoutServerName;
    private boolean useSession = true;
    private boolean redirectAfterValid = true;

    public List<String> getValidateFilters() {
        return Arrays.asList(validateFilters.split(SEPARATOR));
    }

    public void setValidateFilters(String validateFilters) {
        this.validateFilters = validateFilters;
    }

    public List<String> getSignOutFilters() {
        return Arrays.asList(signOutFilters.split(SEPARATOR));
    }

    public void setSignOutFilters(String signOutFilters) {
        this.signOutFilters = signOutFilters;
    }

    public List<String> getAuthFilters() {
        return Arrays.asList(authFilters.split(SEPARATOR));
    }

    public void setAuthFilters(String authFilters) {
        this.authFilters = authFilters;
    }

    public List<String> getAssertionFilters() {
        return Arrays.asList(assertionFilters.split(SEPARATOR));
    }

    public void setAssertionFilters(String assertionFilters) {
        this.assertionFilters = assertionFilters;
    }

    public List<String> getRequestWrapperFilters() {
        return Arrays.asList(reqWrapperFilters.split(SEPARATOR));
    }

    public void setRequestWrapperFilters(String reqWrapperFilters) {
        this.reqWrapperFilters = reqWrapperFilters;
    }

    public String getCasServerUrlPrefix() {
        return casServerUrlPrefix;
    }

    public void setCasServerUrlPrefix(String casServerUrlPrefix) {
        this.casServerUrlPrefix = casServerUrlPrefix;
    }

    public String getCasServerLoginUrl() {
        return casServerLoginUrl;
    }

    public void setCasServerLoginUrl(String casServerLoginUrl) {
        this.casServerLoginUrl = casServerLoginUrl;
    }

    public String getServerName() {
        return serverName;
    }

    public void setServerName(String serverName) {
        this.serverName = serverName;
    }

    public boolean isRedirectAfterValid() {
        return redirectAfterValid;
    }

    public void setRedirectAfterValid(boolean redirectAfterValid) {
        this.redirectAfterValid = redirectAfterValid;
    }

    public boolean isUseSession() {
        return useSession;
    }

    public void setUseSession(boolean useSession) {
        this.useSession = useSession;
    }

    public String getLogoutServerName() {
        return logoutServerName;
    }

    public void setLogoutServerName(String logoutServerName) {
        this.logoutServerName = logoutServerName;
    }

    @Override
    public String toString() {
        return "SpringCasAutoconfig{" +
                "validateFilters=" + validateFilters +
                ", signOutFilters=" + signOutFilters +
                ", authFilters=" + authFilters +
                ", assertionFilters=" + assertionFilters +
                ", reqWrapperFilters=" + reqWrapperFilters +
                ", casServerUrlPrefix=" + casServerUrlPrefix +
                ", casServerLoginUrl=" + casServerLoginUrl +
                ", serverName=" + serverName +
                ", useSession=" + useSession +
                ", redirectAfterValid=" + redirectAfterValid +
                ", logoutServerName=" + logoutServerName +
                "}";
    }
}

CAS配置拦截

/**
 * CAS配置
 * @author zhangyh
 * 2019/10/15
 */
@Configuration
public class CasConfig {
    /**
     * 日志输出
     */
    private static final Logger LOGGER = LoggerFactory.getLogger(CasConfig.class);

    /**
     * 配置Config
     */
    private SpringCasAutoconfig springCasAutoconfig;
    private EncodingFilter encodingFilter;
    private ExclusionUrlProperties exclusionUrlProperties;

    private static boolean CAS_ENABLED = true;

    @Autowired
    public CasConfig(SpringCasAutoconfig springCasAutoconfig,
                     EncodingFilter encodingFilter,
                     ExclusionUrlProperties exclusionUrlProperties) {
        this.springCasAutoconfig = springCasAutoconfig;
        this.encodingFilter=encodingFilter;
        this.exclusionUrlProperties=exclusionUrlProperties;
    }


    /**
     * 加载防止中文乱码编码过滤器
     * @return  FilterRegistrationBean
     */
    @Bean
    public FilterRegistrationBean filterRegistrationBean(){
        FilterRegistrationBean filterRegistrationBean=new FilterRegistrationBean();
        filterRegistrationBean.setFilter(encodingFilter);
        filterRegistrationBean.addUrlPatterns(Constant.URL_SPECIAL);
        filterRegistrationBean.setOrder(Integer.MAX_VALUE-1);
        return  filterRegistrationBean;
    }


    /**
     * 该过滤器负责用户的认证工作
     * 3. 单点登录验证
     */
    @Bean
    public FilterRegistrationBean filterAuthenticationRegistration() {
        FilterRegistrationBean registration = new FilterRegistrationBean();
        registration.setFilter(new AuthenticationFilter());
        // 设定匹配的路径
        registration.addUrlPatterns("/*");
        Map<String,String> initParameters = new HashMap<String, String>(Constant.MAP_SIZE);
        initParameters.put("casServerLoginUrl", springCasAutoconfig.getCasServerLoginUrl());
        initParameters.put("serverName", springCasAutoconfig.getServerName());

        //忽略的url,"|"分隔多个url
        Object[] excludePathArray = exclusionUrlProperties.getExclusionUrls().toArray();
        String excludePaths= StringUtils.join(excludePathArray,"|");
        initParameters.put("ignorePattern", excludePaths);
        registration.setInitParameters(initParameters);
        // 设定加载的顺序
        registration.setOrder(1);
        return registration;
    }

    /**
     * 该过滤器负责对Ticket的校验工作
     * 2.负责Ticket校验
     */
    @Bean
    public FilterRegistrationBean cas20ProxyReceivingTicketValidationFilter() {
        FilterRegistrationBean filterRegistration = new FilterRegistrationBean();
        Cas20ProxyReceivingTicketValidationFilter cas20ProxyReceivingTicketValidationFilter =
                new Cas20ProxyReceivingTicketValidationFilter();
        cas20ProxyReceivingTicketValidationFilter.setServerName(springCasAutoconfig.getServerName());
        filterRegistration.setFilter(cas20ProxyReceivingTicketValidationFilter);
        filterRegistration.setEnabled(CAS_ENABLED);
        if (!springCasAutoconfig.getValidateFilters().isEmpty()) {
            filterRegistration.setUrlPatterns(springCasAutoconfig.getValidateFilters());
        } else {
            filterRegistration.addUrlPatterns(Constant.URL_SPECIAL);
        }
        filterRegistration.addInitParameter("casServerUrlPrefix", springCasAutoconfig.getCasServerUrlPrefix());
        filterRegistration.addInitParameter("serverName", springCasAutoconfig.getServerName());
        filterRegistration.setOrder(5);
        LOGGER.info("cas20ProxyReceivingTicketValidationFilter【5】" + springCasAutoconfig.getValidateFilters());
        return filterRegistration;
    }


    /**
     * 4.该过滤器对HttpServletRequest请求包装,
     * 可通过HttpServletRequest的getRemoteUser()方法获得登录用户的登录名
     */
    @Bean
    public FilterRegistrationBean httpServletRequestWrapperFilter() {
        FilterRegistrationBean filterRegistration = new FilterRegistrationBean();
        filterRegistration.setFilter(new HttpServletRequestWrapperFilter());
        filterRegistration.setEnabled(true);
        if (!springCasAutoconfig.getRequestWrapperFilters().isEmpty()) {
            filterRegistration.setUrlPatterns(springCasAutoconfig.getRequestWrapperFilters());
        } else {
            filterRegistration.addUrlPatterns(Constant.URL_SPECIAL);
        }
        filterRegistration.setOrder(6);
        LOGGER.info("httpServletRequestWrapperFilter【6】" + springCasAutoconfig.getRequestWrapperFilters());
        return filterRegistration;
    }


    /**
     * 该过滤器使得可以通过org.jasig.cas.client.util.AssertionHolder来获取用户的登录名。
     比如AssertionHolder.getAssertion().getPrincipal().getName()。
     这个类把Assertion信息放在ThreadLocal变量中,这样应用程序不在web层也能够获取到当前登录信息
     */
    @Bean
    public FilterRegistrationBean assertionThreadLocalFilter() {
        FilterRegistrationBean filterRegistration = new FilterRegistrationBean();
        filterRegistration.setFilter(new AssertionThreadLocalFilter());
        filterRegistration.setEnabled(true);
        if (!springCasAutoconfig.getAssertionFilters().isEmpty()) {
            filterRegistration.setUrlPatterns(springCasAutoconfig.getAssertionFilters());
        } else {
            filterRegistration.addUrlPatterns(Constant.URL_SPECIAL);
        }
        filterRegistration.setOrder(7);
        LOGGER.info("assertionThreadLocalFilter【7】" + springCasAutoconfig.getAssertionFilters());
        return filterRegistration;
    }



    @Override
    public String toString() {
        return "CasConfig{" +
                "springCasAutoconfig=" + springCasAutoconfig +
                "}";
    }
}

ExclusionUrlProperties这个类主要是配置不拦截路径集合 

@Component
@PropertySource("classpath:config/common.properties")
@ConfigurationProperties(prefix="interceptor.url")
public class ExclusionUrlProperties {

    private List<String> exclusionUrls;

    public List<String> getExclusionUrls() {
        return exclusionUrls;
    }

    public void setExclusionUrls(List<String> exclusionUrls) {
        this.exclusionUrls = exclusionUrls;
    }

}

 对应着这个文件

/**
 * 该过滤器在处理方法中将参数直接进行解码操作,
 * 然后将解码后的参数重新设置到request的attribute中
 * @author cenxu
 */

@Component
public class EncodingFilter implements Filter {
    private static final Logger LOGGER = LoggerFactory.getLogger(EncodingFilter.class);
    protected FilterConfig filterConfig ;

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
    }

    /**
     * 将 inStr 转为 UTF-8 的编码形式
     *
     * @param inStr 输入字符串
     * @return UTF - 8 的编码形式的字符串
     * @throws  UnsupportedEncodingException
     */
    private String toUTF(String inStr) throws UnsupportedEncodingException {
        String outStr = "";
        if (inStr != null) {
            outStr = new String(inStr.getBytes("iso-8859-1"), "UTF-8");
        }
        return outStr;
    }

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain chain) throws
            IOException, ServletException {
        HttpServletRequest request = (HttpServletRequest) servletRequest;
        ServletResponse response = (HttpServletResponse) servletResponse;

        // 获得请求的方式 (1.post or 2.get), 根据不同请求方式进行不同处理
        String method = request.getMethod();
        // 1. 以 post 方式提交的请求 , 直接设置编码为 UTF-8
        if (Constant.POST.equalsIgnoreCase(method)) {
            try {
                request.setCharacterEncoding("UTF-8");
            } catch (UnsupportedEncodingException e) {
                LOGGER.debug(e.toString());
            }
        }
        // 2. 以 get 方式提交的请求
        else {
            // 取出客户提交的参数集
            Enumeration<String> paramNames = request.getParameterNames();
            // 遍历参数集取出每个参数的名称及值
            while (paramNames.hasMoreElements()) {
                // 取出参数名称
                String name = paramNames.nextElement();
                // 根据参数名称取出其值
                String[] values = request.getParameterValues(name);
                // 如果参数值集不为空
                if (values != null) {
                    // 遍历参数值集
                    for (int i = 0; i < values.length; i++) {
                        try {
                            // 回圈依次将每个值调用 toUTF(values[i]) 方法转换参数值的字元编码
                            String vlustr = toUTF(values[i]);
                            values[i] = vlustr;
                        } catch (UnsupportedEncodingException e) {
                            LOGGER.debug(e.toString());
                        }
                    }
                    // 将该值以属性的形式藏在 request
                    request.setAttribute(name, values);
                }
            }

        }
        // 设置响应方式和支持中文的字元集
        response.setContentType("text/html;charset=UTF-8");

        // 继续执行下一个 filter, 无一下个 filter 则执行请求
        chain.doFilter(request, response);
    }

    @Override
    public void destroy() {
        this.filterConfig = null;
    }
}

获取当前登录用户名

/**
 * @Author: zhangYuHui
 * @Date: 2019/10/12 17:59
 */
@Component
public class LocalUserInfoFilter implements Filter {

    private static final Logger LOGGER = LoggerFactory.getLogger(LocalUserInfoFilter.class);


    @Override
    public void init(FilterConfig filterConfig) throws ServletException {

    }

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain chain) throws IOException, ServletException {
        HttpServletRequest request = (HttpServletRequest)servletRequest;
        String reqStr = request.getRequestURI().trim();
        System.out.println(reqStr+".......................");
        String loginName  = getAccountNameFromCas(request);
        request.getSession().setAttribute("loginName",loginName);
        System.out.println(loginName+"================================");
        chain.doFilter(servletRequest, servletResponse);
    }

    @Override
    public void destroy() {

    }

    /**
     * 从cas中获取用户名
     * @param request
     * @return
     */
    public  String getAccountNameFromCas(HttpServletRequest request) {
        Assertion assertion = (Assertion) request.getSession().getAttribute(AbstractCasFilter.CONST_CAS_ASSERTION);
        if(assertion!= null){
            AttributePrincipal principal = assertion.getPrincipal();
            return principal.getName();
        }else {return null;}

    }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
Spring Boot集成CAS单点登录的步骤如下: 1. 配置CAS服务器 首先需要配置CAS服务器,包括安装和配置,这里不再赘述。 2. 引入CAS客户端依赖 在Spring Boot项目中引入CAS客户端依赖,例如: ``` <dependency> <groupId>org.jasig.cas.client</groupId> <artifactId>cas-client-core</artifactId> <version>3.6.</version> </dependency> ``` 3. 配置CAS客户端 在Spring Boot项目中配置CAS客户端,包括CAS服务器地址、CAS客户端地址、CAS登录地址等,例如: ``` cas.server.url=https://cas.example.com/cas cas.client.host.url=https://example.com cas.login.url=https://cas.example.com/cas/login ``` 4. 配置Spring Security 在Spring Boot项目中配置Spring Security,包括登录页面、登录成功后的跳转页面等,例如: ``` @Configuration @EnableWebSecurity public class SecurityConfig extends WebSecurityConfigurerAdapter { @Autowired private CasAuthenticationProvider casAuthenticationProvider; @Autowired private CasAuthenticationEntryPoint casAuthenticationEntryPoint; @Autowired private CasAuthenticationFilter casAuthenticationFilter; @Override protected void configure(HttpSecurity http) throws Exception { http .authorizeRequests() .antMatchers("/login").permitAll() .anyRequest().authenticated() .and() .exceptionHandling() .authenticationEntryPoint(casAuthenticationEntryPoint) .and() .addFilter(casAuthenticationFilter) .logout() .logoutUrl("/logout") .logoutSuccessUrl("/") .invalidateHttpSession(true) .deleteCookies("JSESSIONID") .and() .csrf().disable(); } @Override protected void configure(AuthenticationManagerBuilder auth) throws Exception { auth.authenticationProvider(casAuthenticationProvider); } } ``` 5. 配置CAS认证提供者 在Spring Boot项目中配置CAS认证提供者,例如: ``` @Configuration public class CasConfig { @Value("${cas.server.url}") private String casServerUrl; @Value("${cas.client.host.url}") private String casClientHostUrl; @Value("${cas.login.url}") private String casLoginUrl; @Bean public CasAuthenticationEntryPoint casAuthenticationEntryPoint() { CasAuthenticationEntryPoint entryPoint = new CasAuthenticationEntryPoint(); entryPoint.setLoginUrl(casLoginUrl); entryPoint.setServiceProperties(serviceProperties()); return entryPoint; } @Bean public ServiceProperties serviceProperties() { ServiceProperties serviceProperties = new ServiceProperties(); serviceProperties.setService(casClientHostUrl + "/login/cas"); serviceProperties.setSendRenew(false); return serviceProperties; } @Bean public CasAuthenticationFilter casAuthenticationFilter() throws Exception { CasAuthenticationFilter filter = new CasAuthenticationFilter(); filter.setAuthenticationManager(authenticationManager()); return filter; } @Bean public CasAuthenticationProvider casAuthenticationProvider() { CasAuthenticationProvider provider = new CasAuthenticationProvider(); provider.setServiceProperties(serviceProperties()); provider.setTicketValidator(new Cas30ServiceTicketValidator(casServerUrl)); provider.setUserDetailsService(userDetailsService()); provider.setKey("casAuthProviderKey"); return provider; } @Bean public UserDetailsService userDetailsService() { return new InMemoryUserDetailsManager(Collections.emptyList()); } @Bean public AuthenticationManager authenticationManager() throws Exception { return new ProviderManager(Collections.singletonList(casAuthenticationProvider())); } } ``` 6. 编写登录页面 在Spring Boot项目中编写登录页面,例如: ``` <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>Login</title> </head> <body> <form action="/login/cas" method="post"> <input type="submit" value="Login"> </form> </body> </html> ``` 7. 运行项目 最后运行Spring Boot项目,访问登录页面,输入CAS服务器的用户名和密码,即可实现CAS单点登录

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值