首页 > 学院 > 开发设计 > 正文

Shrio-学习总结-简介

2019-11-08 01:51:46
字体:
来源:转载
供稿:网友

学了段时间的Shiro,自己总结一下shiro。

博客参考这里:http://jinnianshilongnian.iteye.com/blog/2049092

Subject即主体,外部应用与subject进行交互,subject记录了当前操作用户;

SecurityManager即安全管理器,对全部的subject进行安全管理,它是shiro的核心,负责对所有的subject进行安全管理;Realm即领域,相当于datasource数据源,securityManager进行安全认证需要通过Realm获取用户权限数据,比如:如果用户身份数据在数据库那么realm就需要从数据库获取用户身份信息。 注意:不要把realm理解成只是从数据源取数据,在realm中还有认证授权校验的相关的代码。同时Shiro不知道你的用户/权限存储在哪及以何种格式存储;所以我们一般在应用中都需要实现自己的Realm;Authenticator即认证器,对用户身份进行认证,Authenticator是一个接口,shiro默认提供ModularRealmAuthenticator实现类,通过ModularRealmAuthenticator基本上可以满足大多数需求,也可以自定义认证器。ModularRealmAuthenticator提供了单realm认证和多realm认证;代码如下:
    PRotected AuthenticationInfo doAuthenticate(AuthenticationToken authenticationToken) throws AuthenticationException {        assertRealmsConfigured();        Collection<Realm> realms = getRealms();        if (realms.size() == 1) {            return doSingleRealmAuthentication(realms.iterator().next(), authenticationToken);//调用单realm        } else {            return doMultiRealmAuthentication(realms, authenticationToken);//调用多realm        }    }
    protected AuthenticationInfo doSingleRealmAuthentication(Realm realm, AuthenticationToken token) {        if (!realm.supports(token)) {            String msg = "Realm [" + realm + "] does not support authentication token [" +                    token + "].  Please ensure that the appropriate Realm implementation is " +                    "configured correctly or that the realm accepts AuthenticationTokens of this type.";            throw new UnsupportedTokenException(msg);        }        AuthenticationInfo info = realm.getAuthenticationInfo(token);        if (info == null) {            String msg = "Realm [" + realm + "] was unable to find account data for the " +                    "submitted AuthenticationToken [" + token + "].";            throw new UnknownAccountException(msg);        }        return info;    }    protected AuthenticationInfo doMultiRealmAuthentication(Collection<Realm> realms, AuthenticationToken token) {        AuthenticationStrategy strategy = getAuthenticationStrategy();        AuthenticationInfo aggregate = strategy.beforeAllAttempts(realms, token);        if (log.isTraceEnabled()) {            log.trace("Iterating through {} realms for PAM authentication", realms.size());        }        for (Realm realm : realms) {            aggregate = strategy.beforeAttempt(realm, token, aggregate);            if (realm.supports(token)) {                log.trace("Attempting to authenticate token [{}] using realm [{}]", token, realm);                AuthenticationInfo info = null;                Throwable t = null;                try {                    info = realm.getAuthenticationInfo(token);                } catch (Throwable throwable) {                    t = throwable;                    if (log.isDebugEnabled()) {                        String msg = "Realm [" + realm + "] threw an exception during a multi-realm authentication attempt:";                        log.debug(msg, t);                    }                }                aggregate = strategy.afterAttempt(realm, token, info, aggregate, t);            } else {                log.debug("Realm [{}] does not support token {}.  Skipping realm.", realm, token);            }        }        aggregate = strategy.afterAllAttempts(token, aggregate);        return aggregate;    }Authorizer即授权器,用户通过认证器认证通过,在访问功能时需要通过授权器判断用户是否有此功能的操作权限。实现类大体上分为ModularRealmAuthorizer和                        AuthorizingRealm。单realm配置时推荐使用AuthorizingRealm,因为:AuthenticationInfodoGetAuthenticationInfo(AuthenticationToken   token):表示获取身份验证信息;AuthorizationInfodoGetAuthorizationInfo(PrincipalCollection principals):表示根据用户身份获取授权信息。sessionManager即会话管理,shiro框架定义了一套会话管理,它不依赖web容器的session,所以shiro可以使用在非web应用上,也可以将分布式应用的会话集中在一点管理,此特性可使它实现单点登录。sessionDao即会话Dao,AbstractSessionDAO提供了SessionDAO的基础实现,如生成会话ID等;CachingSessionDAO提供了对开发者透明的会话缓存的功能,只需要设置相应的CacheManager即可;MemorySessionDAO直接在内存中进行会话维护;而EnterpriseCacheSessionDAO提供了缓存功能的会话维护,默认情况下使用MapCache实现,内部使用ConcurrentHashMap保存缓存的会话。简单配置:
	<!-- sessionID生成器 -->	<bean id="javaUuidSessionIdGenerator" class="org.apache.shiro.session.mgt.eis.JavaUuidSessionIdGenerator"></bean>	<!-- sessionDAO继承EnterpriseCacheSessionDAO -->	<bean id="sessionDao" class="lee.shiro.session.MySessionDao">		<property name="sessionIdGenerator" ref="javaUuidSessionIdGenerator"></property>		<property name="activeSessionsCacheName" value="shiro-activeSessionCache"></property>	</bean>	<!-- 会话管理器 -->	<bean id="sessionManager" class="org.apache.shiro.session.mgt.DefaultSessionManager">		<property name="sessionDAO" ref="sessionDao"></property>		<property name="deleteInvalidSessions" value="true"></property>		<property name="sessionValidationSchedulerEnabled" value="true"></property>		<property name="globalSessionTimeout" value="1800000"></property>	</bean>
public class MySessionDAO extends CachingSessionDAO {      private JdbcTemplate jdbcTemplate = JdbcTemplateUtils.jdbcTemplate();       protected Serializable doCreate(Session session) {          Serializable sessionId = generateSessionId(session);          assignSessionId(session, sessionId);          String sql = "insert into sessions(id, session) values(?,?)";          jdbcTemplate.update(sql, sessionId, SerializableUtils.serialize(session));          return session.getId();      }  protected void doUpdate(Session session) {      if(session instanceof ValidatingSession && !((ValidatingSession)session).isValid()) {          return; //如果会话过期/停止 没必要再更新了      }          String sql = "update sessions set session=? where id=?";          jdbcTemplate.update(sql, SerializableUtils.serialize(session), session.getId());      }      protected void doDelete(Session session) {          String sql = "delete from sessions where id=?";          jdbcTemplate.update(sql, session.getId());      }      protected Session doReadSession(Serializable sessionId) {          String sql = "select session from sessions where id=?";          List<String> sessionStrList = jdbcTemplate.queryForList(sql, String.class, sessionId);          if(sessionStrList.size() == 0) return null;          return SerializableUtils.deserialize(sessionStrList.get(0));      }  }   CacheManager:缓存控制器,来管理如用户、角色、权限等的缓存的;因为这些数据基本上很少去改变,放到缓存中后可以提高访问的性能;Cryptography:密码模块,Shiro提高了一些常见的加密组件用于如密码加密/解密的;
发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表