• -------------------------------------------------------------
  • ====================================

Cas单点登录(整合shiro版本)

技能 dewbay 5年前 (2019-04-12) 7817次浏览 已收录 0个评论 扫描二维码

Cas单点登录(整合shiro版本)

   单点登录:Single Sign On,简称 SSO,SSO 使得在多个应用系统中,用户只需要登录一次就可以访问所有相互信任的应用系统。

CAS 框架:CAS(Central Authentication Service)是实现 SSO单点登录的框架。
逻辑关系图:(注:图为转载)

分析:
1.图中用户访问cas客户端;
2.需要登录时,重定向到 Cas-Server(Cas 服务),其中 service 为 Cas-Client 路径
(用于 Cas-Server 执行完后返回到指定路径);
3.cas-server 认证用户信息,并生成一个 ticket 返回给用户;
4.用户使用此 ticket 访问 Cas-Client(连接了 Cas-Server 具体应用);
5.Cas-Client 使用 ticket 再次访问 Cas-Server 进行认证;
6.认证成功后返回 Server 指定路径到 Cas-Client,并返回具体登录用户信息,流程结束。

这是原生 Cas 的一套流程,那么我们需要集成到已经使用 Shiro 框架的应用中,如何进行无缝衔接呢?

具体流程:
对于 Cas-Server 就不多说了,官网下载下来后,修改验证用户信息的配置(从数据库中读取数据进行
身份认证),修改配置文件-deployerConfigContext:
(其中 deployerConfigContext.xml 文件是 CAS 专门提出来的供用户修改的配置,其他配置不建议修改)

<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">  
   <property name="driverClassName" value="com.mysql.jdbc.Driver"/>
   <property name="url" value="jdbc:mysql://127.0.0.1:3306/**?characterEncoding=utf8" />  
   <property name="username" value="**" />  
   <property name="password" value="**" />  
</bean> 

注意:其中需要引入包cas-server-support-jdbc-4.0.0.jar(版本号极为重要,与cas-server-core 版本一致即可)
还需要引入 mysql-connector-java-5.1.34.jar(连接 mysql)
连接 Cas-Server 的使用了 Shiro 的应用项目连接的整体操作流程,如下:
1.首先需要引入包shiro-cas 这个包是shirocas连接的通道;
2.修改项目中shiroRealm(自定义的登录验证类,里面包含登录认证、权限认证)
/**

  • shiro登录实现类
  • */
    //重点是集成 CasRealm
    public class ShiroRealm extends CasRealm { private Logger log = LoggerFactory.getLogger(ShiroRealm.class); private TicketValidator ticketValidator; protected TicketValidator ensureTicketValidator()
    {
    if(ticketValidator == null)
    ticketValidator = createTicketValidator();
    return ticketValidator;
    } @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authcToken) throws AuthenticationException {
    CasToken casToken = (CasToken) authcToken;
    if (authcToken == null)
    return null;
    String ticket = (String) casToken.getCredentials();
    TicketValidator ticketValidator = ensureTicketValidator();
    try
    {
    Assertion casAssertion = ticketValidator.validate(ticket, getCasService());
    AttributePrincipal casPrincipal = casAssertion.getPrincipal();
    String userId = casPrincipal.getName();
    log.debug(“Validate ticket : {} in CAS server : {} to retrieve user : {}”, new Object[] {
    ticket, getCasServerUrlPrefix(), userId
    });
    Map attributes = casPrincipal.getAttributes();
    casToken.setUserId(userId);
    String rememberMeAttributeName = getRememberMeAttributeName();
    String rememberMeStringValue = (String)attributes.get(rememberMeAttributeName);
    boolean isRemembered = rememberMeStringValue != null && Boolean.parseBoolean(rememberMeStringValue);
    if(isRemembered)
    casToken.setRememberMe(true);
    /** 此处是封装用户信息
    sUsr su = new sUsr();
    su.setUsrCde(userId);
    sUsr susr = isUsrService.findByCode(su);
    AccessTokenInfo atInfo = new AccessTokenInfo();
    atInfo.setUsrCde(userId);
    //获取 apikey
    AccessTokenInfo ati = accessTokenInfoService.selectOneByObject(atInfo);
    //构建 ShiroUserAccount
    ShiroUserAccount sua = new ShiroUserAccount(susr,ati);
    */
    List principals = CollectionUtils.asList(new Object[] {
    sua, attributes
    });
    PrincipalCollection principalCollection = new SimplePrincipalCollection(principals, getName());
    return new SimpleAuthenticationInfo(principalCollection, ticket);
    }
    catch(TicketValidationException e)
    {
    throw new CasAuthenticationException((new StringBuilder()).append(“Unable to validate ticket [“).append(ticket).append(“]”).toString(), e);
    }
    } @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principal) {
    SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
    //获取登录用户的 Shiro 对象 —主体身份信息(验权)
    ShiroUserAccount shiroUser = (ShiroUserAccount)principal.getPrimaryPrincipal();
    //断言,若对象为空则直接抛出异常
    Assert.notNull(shiroUser,”找不到 principal 中的 SessionVariable—shiroUser”);
    //添加用户拥有的 role
    addRoles(info,shiroUser);
    addPermissions(info,shiroUser);
    return info;
    } } 3.配置 shiro.xml 文件:
    shiroRealm:
    shiroFilter:






    <property name="filters"> <map> <!--添加 cas 的过滤器到 shiro --> <entry key="casFilter" value-ref="casFilter"/> <!--添加登出过滤 --> <entry key="logoutFilter" value-ref="logoutFilter" /> </map> </property> <property name="filterChainDefinitions"> <value> /shiro-cas = casFilter /person/**=authc </value> </property> </bean> casFilter:

    logoutFilter:
    cas 针对 subject 工厂配置:
    <bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager"> <!--单个 realm 使用 realm,如果有多个 realm,使用 realms 属性代替--> <property name="realm" ref="shiroRealm" /> <!-- session 管理器 --> <property name="sessionManager" ref="sessionManager" /> <!-- 缓存管理器 --> <property name="cacheManager" ref="shiroCacheManager" /> <property name="subjectFactory" ref="casSubjectFactory"></property> </bean> 如下是 shiro 剩余的基本配置:

    <!-- sessionIdCookie 的实现,用于重写覆盖容器默认的 JSESSIONID --> <!-- 保证实现了 Shiro 内部 lifecycle 函数的 bean 执行 --> <bean id="lifecycleBeanPostProcessor" class="org.apache.shiro.spring.LifecycleBeanPostProcessor"/> <!-- AOP 式方法级权限检查 --> <bean class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator" depends-on="lifecycleBeanPostProcessor"> <property name="proxyTargetClass" value="true" /> </bean> <bean class="org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor"> <property name="securityManager" ref="securityManager"/> 作者:Cx_ 轩
    来源:CSDN
    原文:https://blog.csdn.net/qq_25223941/article/details/78316108
    版权声明:本文为博主原创文章,转载请附上博文链接!

露水湾 , 版权所有丨如未注明 , 均为原创丨本网站采用BY-NC-SA协议进行授权
转载请注明原文链接:Cas单点登录(整合shiro版本)
喜欢 (1)
[]
分享 (0)
关于作者:
发表我的评论
取消评论

表情 贴图 加粗 删除线 居中 斜体 签到

Hi,您需要填写昵称和邮箱!

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址