今天是:
带着程序的旅程,每一行代码都是你前进的一步,每个错误都是你成长的机会,最终,你将抵达你的目的地。
title

Spring中实现Shiro认证和第三方认证

1Spring中配置Shiro


<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" xsi:schemaLocation="
      http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
      http://www.springframework.org/schema/context  http://www.springframework.org/schema/context/spring-context-4.0.xsd"
       default-lazy-init="true">

    <description>Shiro Configuration</description>

    <!-- 加载配置属性文件 -->
    <context:property-placeholder ignore-unresolvable="true" location="classpath:/properties/zlennon.properties" />

    <!-- Shiro权限过滤过滤器定义 -->
    <bean name="shiroFilterChainDefinitions" class="java.lang.String">
        <constructor-arg>
            <value>
                /static/** = anon
                ${adminPath}/login = authc
                ${adminPath}/** = user
            </value>
        </constructor-arg>
    </bean>

    <!-- 安全认证过滤器 -->
    <bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">
        <property name="securityManager" ref="securityManager" /><!--
      <property name="loginUrl" value="${cas.server.url}?service=${cas.project.url}${adminPath}/cas" /> -->
        <property name="loginUrl" value="/login" />
        <property name="successUrl" value="/?login" />
        <property name="filters">
            <map>
                <entry key="cas" value-ref="casFilter"/>
                <entry key="authc" value-ref="formAuthenticationFilter"/>
            </map>
        </property>
        <property name="filterChainDefinitions">
            <ref bean="shiroFilterChainDefinitions"/>
        </property>
    </bean>

    <!-- CAS认证过滤器 -->
    <bean id="casFilter" class="org.apache.shiro.cas.CasFilter">
        <property name="failureUrl" value="${adminPath}/login"/>
    </bean>

    <!-- 定义Shiro安全管理配置 -->
    <bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">
        <property name="realm" ref="systemAuthorizingRealm" /
        <!--<property name="sessionManager" ref="sessionManager" /> -->
        <property name="cacheManager" ref="shiroCacheManager" />
    </bean>

    <!-- 自定义会话管理配置 -->
    <bean id="sessionManager" class="com.zlennon.core.security.shiro.session.SessionManager">
        <property name="sessionDAO" ref="sessionDAO"/>

        <!-- 会话超时时间,单位:毫秒  -->
        <property name="globalSessionTimeout" value="${session.sessionTimeout}"/>

        <!-- 定时清理失效会话, 清理用户直接关闭浏览器造成的孤立会话   -->
        <property name="sessionValidationInterval" value="${session.sessionTimeoutClean}"/>
        <!--      <property name="sessionValidationSchedulerEnabled" value="false"/> -->
        <property name="sessionValidationSchedulerEnabled" value="true"/>

        <property name="sessionIdCookie" ref="sessionIdCookie"/>
        <property name="sessionIdCookieEnabled" value="true"/>
    </bean>

    <!-- 指定本系统SESSIONID, 默认为: JSESSIONID 问题: 与SERVLET容器名冲突, 如JETTY, TOMCAT 等默认JSESSIONID,
        当跳出SHIRO SERVLET时如ERROR-PAGE容器会为JSESSIONID重新分配值导致登录会话丢失! -->
    <bean id="sessionIdCookie" class="org.apache.shiro.web.servlet.SimpleCookie">
        <constructor-arg name="name" value="zlennon.session.id"/>
    </bean>

    <!-- 自定义Session存储容器 -->
    <bean id="sessionDAO" class="com.zlennon.core.security.shiro.session.CacheSessionDAO">
        <property name="sessionIdGenerator" ref="idGen" />
        <property name="activeSessionsCacheName" value="activeSessionsCache" />
        <property name="cacheManager" ref="shiroCacheManager" />
    </bean>

    <!-- 定义授权缓存管理器 -->
    <!--   <bean id="shiroCacheManager" class="com.zlennon.core.security.shiro.cache.SessionCacheManager" /> -->
    <bean id="shiroCacheManager" class="org.nutz.j2cache.shiro.J2CacheManager">
    </bean>

    <!-- 保证实现了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"/>
    </bean>

</beans>

spirng-mvc.xml

<!-- 支持Shiro对Controller的方法级AOP安全控制 begin-->
<bean class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator" depends-on="lifecycleBeanPostProcessor">
   <property name="proxyTargetClass" value="true" />
</bean>

<bean class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver">
   <property name="exceptionMappings">
      <props>
         <prop key="org.apache.shiro.authz.UnauthorizedException">error/403</prop>
         <prop key="java.lang.Throwable">error/500</prop>
      </props>
      </property>
</bean>
<!-- 支持Shiro对Controller的方法级AOP安全控制 end -->

2第三方认证

第三方 认证有企业的统一身份来认证,认证完之后在session中获取认证信息。

HttpSession session =request.getSession();
SSOPrincipal ssoPrincipal = ((SSOPrincipal) session.getAttribute(SSOPrincipal.NAME_OF_SESSION_ATTR));  
model.addAttribute("ssoPrincipal",ssoPrincipal);
Subject currentUser = SecurityUtils.getSubject();
UsernamePasswordToken token = new UsernamePasswordToken(ssoPrincipal.getAdAccounts()[0],false);
currentUser.login(token);

UsernamePasswordToken

public class UsernamePasswordToken extends org.apache.shiro.authc.UsernamePasswordToken {

   private static final long serialVersionUID = 1L;

   private boolean mobileLogin;
   private boolean isReqPassWord=true;
   
   public UsernamePasswordToken(String username,Boolean isReqPassWord) {
      super(username,"");
      this.isReqPassWord=isReqPassWord;
   }

   public UsernamePasswordToken(String username, char[] password,
         boolean rememberMe, String host, String captcha, boolean mobileLogin) {
      super(username, password, rememberMe, host);
      this.captcha = captcha;
      this.mobileLogin = mobileLogin;
   }

/*getter setter*/

}

CredentialsMatcher

public class CredentialsMatcher extends HashedCredentialsMatcher {
    private final static Logger LOGGER = LoggerFactory.getLogger(CredentialsMatcher.class);

    public CredentialsMatcher(String hashAlgorithmName){
        super(hashAlgorithmName);
    }
    @Override
    public boolean doCredentialsMatch(AuthenticationToken token, AuthenticationInfo info) {

        UsernamePasswordToken userNameLoginToken = (UsernamePasswordToken) token;
        //如果是免密码登陆,直接返回
        if (!userNameLoginToken.isReqPassWord()) {
            return true;
        }
        Object tokenHashedCredentials = this.hashProvidedCredentials(token, info);
        Object accountCredentials = this.getCredentials(info);
        return this.equals(tokenHashedCredentials, accountCredentials);
    }
}
分享到:

专栏

类型标签

网站访问总量