• springboot + shiro + cas4.2.7 实战


    1. 下载地址 https://github.com/apereo/cas/archive/v4.2.7.zip

    2. 解压后, 用intellj idea 打开

    3. 执行 gradle build -x test ,打包编译

    4. 取消https,能够支持直接http

    cas.properties 修改两个地方

    复制代码
    # Decides whether SSO cookie should be created only under secure connections.
     tgc.secure=false
    
    # The expiration value of the SSO cookie
    # tgc.maxAge=-1
    
    # The name of the SSO cookie
    # tgc.name=TGC
    
    # The path to which the SSO cookie will be scoped
    # tgc.path=/cas
    
    # The expiration value of the SSO cookie for long-term authentications
    # tgc.remember.me.maxAge=1209600
    
    # Decides whether SSO Warning cookie should be created only under secure connections.
     warn.cookie.secure=false
    复制代码

    casLoginView.jsp

    复制代码
    <jsp:directive.include file="includes/top.jsp" />
    
    <%--<c:if test="${not pageContext.request.secure}">
        <div id="msg" class="errors">
            <h2><spring:message code="screen.nonsecure.title" /></h2>
            <p><spring:message code="screen.nonsecure.message" /></p>
        </div>
    </c:if>--%>
    复制代码

    注销上面的代码

    HTTPSandIMAPS-10000001.json 中增加http的service

    复制代码
    {
      "@class" : "org.jasig.cas.services.RegexRegisteredService",
      "serviceId" : "^(https|imaps|http)://.*",
      "name" : "HTTPS and IMAPS",
      "id" : 10000001,
      "description" : "This service definition authorized all application urls that support HTTPS and IMAPS protocols.",
      "proxyPolicy" : {
        "@class" : "org.jasig.cas.services.RefuseRegisteredServiceProxyPolicy"
      },
      "evaluationOrder" : 10000,
      "usernameAttributeProvider" : {
        "@class" : "org.jasig.cas.services.DefaultRegisteredServiceUsernameProvider"
      },
      "logoutType" : "BACK_CHANNEL",
      "attributeReleasePolicy" : {
        "@class" : "org.jasig.cas.services.ReturnAllowedAttributeReleasePolicy",
        "principalAttributesRepository" : {
          "@class" : "org.jasig.cas.authentication.principal.DefaultPrincipalAttributesRepository"
        },
        "authorizedToReleaseCredentialPassword" : false,
        "authorizedToReleaseProxyGrantingTicket" : false
      },
      "accessStrategy" : {
        "@class" : "org.jasig.cas.services.DefaultRegisteredServiceAccessStrategy",
        "enabled" : true,
        "ssoEnabled" : true
      }
    }

    5. 修改cas的认证方式,包括jdbc、 自定义密码加密等

    5.1 修改 cas-server-webapp 的依赖,修改 该工程下build.gradle

    5.2 修改cas.properties

     cas.jdbc.authn.query.sql=SELECT username,pwd,salt,`status` FROM sys_user WHERE username = ?
     cas.jdbc.authn.search.password=root
     cas.jdbc.authn.search.user=root

    5.3 自定义密码加密 CustomEncoder

    package org.jasig.cas.adaptors.jdbc;
    
    import org.apache.shiro.crypto.RandomNumberGenerator;
    import org.apache.shiro.crypto.SecureRandomNumberGenerator;
    import org.apache.shiro.crypto.hash.SimpleHash;
    import org.apache.shiro.util.ByteSource;
    import org.springframework.beans.factory.annotation.Value;
    
    /**
     * Created by 肖建锋 on 2017/3/25.
     */
    public class CustomEncoder {
        /** 随机字符生产工具 */
        private RandomNumberGenerator randomNumberGenerator = new SecureRandomNumberGenerator();
    
        /** 加密方式 */
        private String algorithmName = "sha";
    
        /** 多重加密次数 */
        private int hashIterations = 2;
    
        /**
         * 配置随机字符生产工具
         * @param randomNumberGenerator
         *
         * @author xiaojf 2016-01-07 01:46
         */
        public void setRandomNumberGenerator(RandomNumberGenerator randomNumberGenerator) {
            this.randomNumberGenerator = randomNumberGenerator;
        }
    
        /**
         * 配置加密方式
         * @param algorithmName
         *
         * @author xiaojf 2016-01-07 01:46
         */
        public void setAlgorithmName(String algorithmName) {
            this.algorithmName = algorithmName;
        }
    
        /**
         * 配置重复加密次数
         * @param hashIterations
         *
         * @author xiaojf 2016-01-07 01:46
         */
        public void setHashIterations(int hashIterations) {
            this.hashIterations = hashIterations;
        }
    
        /**
         * 密码加密
         *  @param pwd
         *  @param salt
         * @author xiaojf 2016-01-07 01:46
         */
        public String encryptPassword(String pwd,String salt) {
            return new SimpleHash(algorithmName, pwd, ByteSource.Util.bytes(salt), hashIterations).toHex();
        }
        /**
         * 根据私钥加密
         * @param value 要加密字段
         * @param salt 密钥
         * @author hp
         * @return 加密后字段
         * 2016-05-07 01:46
         */
        public String encrypt(String value , String salt) {
            return  new SimpleHash(algorithmName, value, ByteSource.Util.bytes(salt), hashIterations).toHex();
        }
    
        /**
         * 获取加密后的新密码
         *
         * @param pwd 密码
         * @param salt 盐
         * @return 新密码
         * @author xiaojf  2016-5-7 15:37:54
         */
        public String getEncryptPassword(String pwd,String salt){
            String newPassword = new SimpleHash(algorithmName, pwd, ByteSource.Util.bytes(salt), hashIterations).toHex();
    
            return newPassword;
        }
    
        /**
         * @param args the input arguments
         * @author xiaojf  2016-5-7 15:37:54
         */
        public static void main(String[] args) {
            /*SysUser sysUser = new SysUser();
            sysUser.setUsername("super");
            sysUser.setPwd("admin");*/
            String s = new CustomEncoder().encrypt("super","e910c85b7f5c5e789d50fafcfa5d4efc");
            System.out.println(s);
        }
    }

    5.4 自定义用户认证方式

    package org.jasig.cas.adaptors.jdbc;
    
    import org.apache.commons.lang3.StringUtils;
    import org.jasig.cas.authentication.HandlerResult;
    import org.jasig.cas.authentication.PreventedException;
    import org.jasig.cas.authentication.UsernamePasswordCredential;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.beans.factory.annotation.Qualifier;
    import org.springframework.beans.factory.annotation.Value;
    import org.springframework.dao.DataAccessException;
    import org.springframework.dao.IncorrectResultSizeDataAccessException;
    import org.springframework.jdbc.support.rowset.SqlRowSet;
    import org.springframework.stereotype.Component;
    
    import javax.security.auth.login.AccountNotFoundException;
    import javax.security.auth.login.FailedLoginException;
    import javax.sql.DataSource;
    import javax.validation.constraints.NotNull;
    import java.security.GeneralSecurityException;
    import java.util.Map;
    
    /**
     * Class that if provided a query that returns a password (parameter of query
     * must be username) will compare that password to a translated version of the
     * password provided by the user. If they match, then authentication succeeds.
     * Default password translator is plaintext translator.
     *
     * @author Scott Battaglia
     * @author Dmitriy Kopylenko
     * @author Marvin S. Addison
     *
     * @since 3.0.0
     */
    @Component("queryDatabaseAuthenticationHandler2")
    public class QueryDatabaseAuthenticationHandler2 extends AbstractJdbcUsernamePasswordAuthenticationHandler {
    
        @NotNull
        private String sql;
    
        @Override
        protected final HandlerResult authenticateUsernamePasswordInternal(final UsernamePasswordCredential credential)
                throws GeneralSecurityException, PreventedException {
    
            if (StringUtils.isBlank(this.sql) || getJdbcTemplate() == null) {
                throw new GeneralSecurityException("Authentication handler is not configured correctly");
            }
    
            final String username = credential.getUsername();
            try {
                Map<String, Object> map = getJdbcTemplate().queryForMap(sql, username);
                final String dbPassword  = map.get("pwd")+"";
                String salt = map.get("salt")+"";
                int status = Integer.parseInt(map.get("status")+"");
                final String encryptedPassword = new CustomEncoder().encryptPassword(credential.getPassword(),salt);
    
                if (!dbPassword.equals(encryptedPassword)) {
                    throw new FailedLoginException("Password does not match value on record.");
                }
            } catch (final IncorrectResultSizeDataAccessException e) {
                if (e.getActualSize() == 0) {
                    throw new AccountNotFoundException(username + " not found with SQL query");
                } else {
                    throw new FailedLoginException("Multiple records found for " + username);
                }
            } catch (final DataAccessException e) {
                throw new PreventedException("SQL exception while executing query for " + username, e);
            }
            return createHandlerResult(credential, this.principalFactory.createPrincipal(username), null);
        }
    
        /**
         * @param sql The sql to set.
         */
        @Autowired
        public void setSql(@Value("${cas.jdbc.authn.query.sql:}") final String sql) {
            this.sql = sql;
        }
    
        @Override
        @Autowired(required = false)
        public void setDataSource(@Qualifier("queryDatabaseDataSource") final DataSource dataSource) {
            super.setDataSource(dataSource);
        }
    }

    6. 自定义数据源

    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xmlns:p="http://www.springframework.org/schema/p"
           xmlns:c="http://www.springframework.org/schema/c"
           xmlns:aop="http://www.springframework.org/schema/aop"
           xmlns:tx="http://www.springframework.org/schema/tx"
           xmlns:context="http://www.springframework.org/schema/context"
           xmlns:util="http://www.springframework.org/schema/util"
           xmlns:sec="http://www.springframework.org/schema/security"
           xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
           http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd
           http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd
           http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
           http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security.xsd
           http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd">
    
        <!-- 设置druid数据源 -->
        <bean id="queryDatabaseDataSource" class="com.alibaba.druid.pool.DruidDataSource" init-method="init" destroy-method="close">
            <property name="url" value="jdbc:mysql://localhost:3306/tomorrow?characterEncoding=utf-8" />
            <property name="username" value="root" />
            <property name="password" value="root" />
            <property name="driverClassName" value="com.mysql.jdbc.Driver"></property>
        </bean>
    
    </beans>

    7. 修改 cas默认的用户校验方式,注入我们上面定义的规则 deployerConfigContext.xml

    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xmlns:context="http://www.springframework.org/schema/context"
           xmlns:p="http://www.springframework.org/schema/p"
           xmlns:c="http://www.springframework.org/schema/c"
           xmlns:aop="http://www.springframework.org/schema/aop"
           xmlns:tx="http://www.springframework.org/schema/tx"
           xmlns:util="http://www.springframework.org/schema/util"
           xmlns:sec="http://www.springframework.org/schema/security"
           xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
           http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd
           http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd
           http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
           http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security.xsd
           http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd">
    
    
        <util:map id="authenticationHandlersResolvers">
            <entry key-ref="proxyAuthenticationHandler" value-ref="proxyPrincipalResolver" />
            <entry key-ref="primaryAuthenticationHandler" value-ref="primaryPrincipalResolver" />
        </util:map>
    
        <util:list id="authenticationMetadataPopulators">
            <ref bean="successfulHandlerMetaDataPopulator" />
            <ref bean="rememberMeAuthenticationMetaDataPopulator" />
        </util:list>
    
        <bean id="attributeRepository" class="org.jasig.services.persondir.support.NamedStubPersonAttributeDao"
              p:backingMap-ref="attrRepoBackingMap" />
    
        <alias name="queryDatabaseAuthenticationHandler2" alias="primaryAuthenticationHandler" />
        <alias name="personDirectoryPrincipalResolver" alias="primaryPrincipalResolver" />
    
        <util:map id="attrRepoBackingMap">
            <entry key="uid" value="uid" />
            <entry key="eduPersonAffiliation" value="eduPersonAffiliation" />
            <entry key="groupMembership" value="groupMembership" />
            <entry>
                <key><value>memberOf</value></key>
                <list>
                    <value>faculty</value>
                    <value>staff</value>
                    <value>org</value>
                </list>
            </entry>
        </util:map>
    
        <alias name="serviceThemeResolver" alias="themeResolver" />
    
        <alias name="jsonServiceRegistryDao" alias="serviceRegistryDao" />
    
        <alias name="defaultTicketRegistry" alias="ticketRegistry" />
        
        <alias name="ticketGrantingTicketExpirationPolicy" alias="grantingTicketExpirationPolicy" />
        <alias name="multiTimeUseOrTimeoutExpirationPolicy" alias="serviceTicketExpirationPolicy" />
    
        <alias name="anyAuthenticationPolicy" alias="authenticationPolicy" />
        <alias name="acceptAnyAuthenticationPolicyFactory" alias="authenticationPolicyFactory" />
    
        <bean id="auditTrailManager"
              class="org.jasig.inspektr.audit.support.Slf4jLoggingAuditTrailManager"
              p:entrySeparator="${cas.audit.singleline.separator:|}"
              p:useSingleLine="${cas.audit.singleline:false}"/>
    
        <alias name="neverThrottle" alias="authenticationThrottle" />
    
        <util:list id="monitorsList">
            <ref bean="memoryMonitor" />
            <ref bean="sessionMonitor" />
        </util:list>
    
        <alias name="defaultPrincipalFactory" alias="principalFactory" />
        <alias name="defaultAuthenticationTransactionManager" alias="authenticationTransactionManager" />
        <alias name="defaultPrincipalElectionStrategy" alias="principalElectionStrategy" />
        <alias name="tgcCipherExecutor" alias="defaultCookieCipherExecutor" />
    
    </beans>

     8. 打war包,复制到tomcat下启动,或者直接用idea运行

     到这里cas安装修改完成了,接下来是修改springboot+shiro + cas(重点部分,已经用红色标出)

    9. 加入shiro-cas依赖

    compile ("org.apache.shiro:shiro-cas:1.3.2")

    10. 修改 ShiroConfiguration.java 自定义cas filter

    @Bean
        public CasFilter casFilter() {
            CasFilter casFilter = new CasFilter();
            casFilter.setFailureUrl("/error/403");
            casFilter.setSuccessUrl("/");
            return casFilter;
        }

    11. 自定义 cas realm

    @Bean
        public MyCasRealm myCasRealm(RetryLimitHashedCredentialsMatcher credentialsMatcher) {
            MyCasRealm casRealm = new MyCasRealm();
            casRealm.setCachingEnabled(true);
    
            casRealm.setCasServerUrlPrefix("http://localhost:8080/cas");
            casRealm.setCasService("http://localhost:8000/shiro-cas");
    
            return  casRealm;
        }

    12. 自定义多点登出逻辑,不能使用shiro自带的logout filter

    package cn.xiaojf.today.sys.web.controller;
    
    import cn.xiaojf.today.base.constant.SystemConstant;
    import cn.xiaojf.today.base.model.CommonResult;
    import cn.xiaojf.today.base.exception.BusinessException;
    import cn.xiaojf.today.base.web.controller.BaseController;
    import cn.xiaojf.today.log.OperationType;
    import cn.xiaojf.today.log.annotation.OperateLog;
    import cn.xiaojf.today.sys.entity.SysUser;
    import cn.xiaojf.today.sys.service.SysUserService;
    import org.apache.commons.lang3.StringUtils;
    import org.apache.shiro.SecurityUtils;
    import org.apache.shiro.authc.AuthenticationException;
    import org.apache.shiro.authc.UsernamePasswordToken;
    import org.apache.shiro.subject.Subject;
    import org.apache.shiro.web.session.HttpServletSession;
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.RestController;
    import org.springframework.web.servlet.ModelAndView;
    
    import javax.servlet.http.HttpSession;
    import java.util.Set;
    
    /**
     * @author xiaojf 2017/2/9 15:48.
     */
    @RestController
    @RequestMapping("/login")
    public class LoginController {
        @Autowired
        private SysUserService userService;
    
        Logger logger = LoggerFactory.getLogger(LoginController.class);
    
        @RequestMapping("index")
        public ModelAndView index() {
            ModelAndView mv = new ModelAndView("/login");
            return mv;
        }
    
        @RequestMapping("out")
        public ModelAndView out() {
            SecurityUtils.getSubject().logout();
            ModelAndView view = new ModelAndView();
            view.setViewName("redirect:http://localhost:8080/cas/logout");
            return view;
        }
    
        @RequestMapping("auth")
        @OperateLog(module = OperationType.LOGIN)
        public ModelAndView auth(String username, String password, boolean rememberMe, HttpSession session) {
            ModelAndView mv = new ModelAndView("/");
            try {
                Subject subject = SecurityUtils.getSubject();
                UsernamePasswordToken token = new UsernamePasswordToken(username, password, rememberMe);
                subject.login(token);
    
                SysUser user = userService.getByUsername(username);
                //在session中保存当前用户的个人信息
                session.setAttribute(SystemConstant.SYS_CURRENT_USER, user);
                //在session中保存用户的r_path
                Set<String> rpathSet = userService.loadUserRPath(user.getId());
                String rpath = StringUtils.join(rpathSet, SystemConstant.DATA_SPLIT_CHAR);
                session.setAttribute(SystemConstant.SYS_CURRENT_USER_RPATH, rpath);
    
            } catch (IllegalArgumentException e) {
                mv.setViewName("/login/index");
                mv.addObject("errMsg","参数异常");
                logger.error(e.getMessage(), e.getStackTrace());
            } catch (AuthenticationException e) {
                logger.error(e.getMessage(), e.getStackTrace());
                mv.setViewName("/login/index");
                mv.addObject("errMsg","认证失败");
            } catch (BusinessException e) {
                mv.setViewName("/login/index");
                mv.addObject("errMsg","登录异常");
    
                logger.error(e.getMessage(), e.getStackTrace());
            } catch (Exception e) {
                mv.setViewName("/login/index");
                mv.addObject("errMsg","登录异常");
                logger.error(e.getMessage(), e.getStackTrace());
            }
            return mv;
        }
    
    }

    13. 完整的 ShiroConfiguration

    package cn.xiaojf.today.shiro.configuration;
    
    import at.pollux.thymeleaf.shiro.dialect.ShiroDialect;
    import cn.xiaojf.today.sys.security.credentials.RetryLimitHashedCredentialsMatcher;
    import cn.xiaojf.today.sys.security.filter.RoleAuthorizationFilter;
    import cn.xiaojf.today.sys.security.realm.MyCasRealm;
    import cn.xiaojf.today.sys.security.realm.UsernameRealm;
    import cn.xiaojf.today.sys.service.SysResService;
    import org.apache.shiro.cas.CasFilter;
    import org.apache.shiro.spring.LifecycleBeanPostProcessor;
    import org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor;
    import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
    import org.apache.shiro.web.filter.authc.LogoutFilter;
    import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
    import org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator;
    import org.springframework.boot.web.servlet.FilterRegistrationBean;
    import org.springframework.context.ApplicationContext;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.web.filter.DelegatingFilterProxy;
    
    import javax.servlet.Filter;
    import java.util.LinkedHashMap;
    import java.util.Map;
    
    /**
     * shiro配置
     * @author xiaojf 2017/2/10 11:30.
     */
    @Configuration
    public class ShiroConfiguration {
        @Bean
        public FilterRegistrationBean filterRegistrationBean() {
            FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean();
            filterRegistrationBean.setFilter(new DelegatingFilterProxy("shiroFilter"));
            filterRegistrationBean.addInitParameter("targetFilterLifecycle", "true");
            filterRegistrationBean.setEnabled(true);
            filterRegistrationBean.addUrlPatterns("/*");
            return filterRegistrationBean;
        }
    
        @Bean
        public RetryLimitHashedCredentialsMatcher credentialsMatcher() {
            RetryLimitHashedCredentialsMatcher credentialsMatcher = new RetryLimitHashedCredentialsMatcher();
            credentialsMatcher.setHashAlgorithmName("sha");
            credentialsMatcher.setHashIterations(2);
            credentialsMatcher.setStoredCredentialsHexEncoded(true);
            credentialsMatcher.setRetryCount(5);
            credentialsMatcher.setRetryTime(1800000);
            return credentialsMatcher;
        }
    
        @Bean
        public UsernameRealm usernameRealm(RetryLimitHashedCredentialsMatcher credentialsMatcher) {
            UsernameRealm usernameRealm = new UsernameRealm();
            usernameRealm.setCredentialsMatcher(credentialsMatcher);
            usernameRealm.setCachingEnabled(true);
            return  usernameRealm;
        }
    
        @Bean
        public MyCasRealm myCasRealm(RetryLimitHashedCredentialsMatcher credentialsMatcher) {
            MyCasRealm casRealm = new MyCasRealm();
    //        casRealm.setCredentialsMatcher(credentialsMatcher);
            casRealm.setCachingEnabled(true);
    
            casRealm.setCasServerUrlPrefix("http://localhost:8080/cas");
            casRealm.setCasService("http://localhost:8000/shiro-cas");
    
            return  casRealm;
        }
    
        @Bean
        public LifecycleBeanPostProcessor lifecycleBeanPostProcessor() {
            return new LifecycleBeanPostProcessor();
        }
    
        @Bean
        public DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator() {
            DefaultAdvisorAutoProxyCreator daap = new DefaultAdvisorAutoProxyCreator();
            daap.setProxyTargetClass(true);
            return daap;
        }
    
        /*@Bean
        public DefaultWebSecurityManager securityManager(UsernameRealm usernameRealm) {
            DefaultWebSecurityManager dwsm = new DefaultWebSecurityManager();
            dwsm.setRealm(usernameRealm);
            return dwsm;
        }*/
    
        @Bean
        public DefaultWebSecurityManager securityManager(MyCasRealm myCasRealm) {
            DefaultWebSecurityManager dwsm = new DefaultWebSecurityManager();
            dwsm.setRealm(myCasRealm);
            return dwsm;
        }
    
        @Bean
        public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(DefaultWebSecurityManager defaultWebSecurityManager) {
            AuthorizationAttributeSourceAdvisor aasa = new AuthorizationAttributeSourceAdvisor();
            aasa.setSecurityManager(defaultWebSecurityManager);
            return aasa;
        }
    
        @Bean
        public CasFilter casFilter() {
            CasFilter casFilter = new CasFilter();
            casFilter.setFailureUrl("/error/403");
            casFilter.setSuccessUrl("/");
            return casFilter;
        }
    
        @Bean(name = "shiroFilter")
        public ShiroFilterFactoryBean shiroFilterFactoryBean(DefaultWebSecurityManager securityManager, CasFilter casFilter,ApplicationContext context) {
            ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
            shiroFilterFactoryBean.setSecurityManager(securityManager);
            shiroFilterFactoryBean.setLoginUrl("http://localhost:8080/cas/login?service=http://localhost:8000/shiro-cas");
            shiroFilterFactoryBean.setUnauthorizedUrl("http://localhost:8080/cas/login?service=http://localhost:8000/shiro-cas");
    
            Map<String, Filter> filters = new LinkedHashMap<>();
            filters.put("role", new RoleAuthorizationFilter());
            filters.put("cas",casFilter);
    
            shiroFilterFactoryBean.getFilters().putAll(filters);
    
            SysResService resService = context.getBean(SysResService.class);
            loadShiroFilterChain(shiroFilterFactoryBean,resService);
            return shiroFilterFactoryBean;
        }
    
        private void loadShiroFilterChain(ShiroFilterFactoryBean shiroFilterFactoryBean,SysResService resService) {
            Map<String, String> filterChainDefinitionMap = new LinkedHashMap<>();
    //        filterChainDefinitionMap.put("/login/index", "anon");
            filterChainDefinitionMap.put("/error/403", "anon");
            filterChainDefinitionMap.put("/error/404", "anon");
            filterChainDefinitionMap.put("/error/500", "anon");
    //        filterChainDefinitionMap.put("/login/auth", "anon");
            filterChainDefinitionMap.put("login/out", "authc");
            filterChainDefinitionMap.put("/plugins/**", "anon");
            filterChainDefinitionMap.put("/css/**", "anon");
            filterChainDefinitionMap.put("/js/**", "anon");
            filterChainDefinitionMap.put("/images/**", "anon");
    
            filterChainDefinitionMap.put("/shiro-cas", "cas");
    
            filterChainDefinitionMap = resService.loadFilterChainDefinitions(filterChainDefinitionMap);
    
            filterChainDefinitionMap.put("/**", "role[ROLE_SUPER]");
    
            shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);
        }
    
        @Bean
        public ShiroDialect shiroDialect() {
            return new ShiroDialect();
        }
    }

    14. 修改完成以后, 直接访问自己的项目会自动的跳转到cas的登陆页面,登陆完成后会跳转到自己项目的首页,注意主要是下面这句话的效果

    shiroFilterFactoryBean.setLoginUrl("http://localhost:8080/cas/login?service=http://localhost:8000/shiro-cas");

    首先登陆的请求被转发到
    http://localhost:8080/cas/login
    然后登陆成功会返回ticket,并重定向到
    http://localhost:8000/shiro-cas

    shiro-cas 会通过cas filter 拦截到shiro-cas,然后根据返回的username 对用户进行授权



    还有一点需要注意的时候 , cas 默认接受的参数名称是 username, password ,可以在cas.properties 中修改默认, 下面是我的登陆表单代码,仅供参考
    <form action="/login/auth" method="post">
                <input id="username" type="text" name="username" class="username" placeholder="用户名">
                <input id="pwd" type="password" name="pwd" class="password" placeholder="密码">
                <button type="submit">登 录</button>
            </form>
  • 相关阅读:
    二分查找(Binary Search)的几种变种形式
    深入理解jvm虚拟机读书笔记-垃圾收集器与内存分配策略(二)
    深入理解jvm虚拟机读书笔记-垃圾收集器与内存分配策略(一)
    Java8函数式编程
    Spring DBUnit 插入数据的时候如何处理自增ID
    IDEA Debug 技巧总结
    声明
    Mybatis最详细笔记
    关于jdbc概述
    SpringAOP(动态代理)
  • 原文地址:https://www.cnblogs.com/xiaojf/p/6619060.html
Copyright © 2020-2023  润新知