sessionId控制单点登陆

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


<bean id="rememberMeCookie" class="org.apache.shiro.web.servlet.SimpleCookie">
<constructor-arg value="rememberMe"/>
<property name="httpOnly" value="true"/>
<property name="maxAge" value="2592000"/><!-- 30天 -->
</bean>

<!-- rememberMe管理器 -->
<bean id="rememberMeManager" class="org.apache.shiro.web.mgt.CookieRememberMeManager">
<!-- rememberMe cookie加密的密钥 每个项目都不一样 默认AES算法 用下面的代码产生不同的密码
AesCipherService aes = new AesCipherService();
byte[] key = aes.generateNewKey().getEncoded();
String base64 = Base64.encodeToString(key);
-->
<property name="cipherKey" value="#{T(org.apache.shiro.codec.Base64).decode('kbFQXD6nkE8QuvzqlV9UYA==')}"/>
<property name="cookie" ref="rememberMeCookie"/>
</bean>

<bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">
<property name="realm" ref="securityService"/>
<!-- 可以配置多个Realm,其实会把realms属性赋值给ModularRealmAuthenticator的realms属性 -->
<!--<property name="realms">-->
<!--<list>-->
<!--<ref bean="securityService" />-->
<!--<ref bean="frontSecurityService"/>-->
<!--</list>-->
<!--</property>-->
<property name="rememberMeManager" ref="rememberMeManager"/>
<property name="sessionManager" ref="sessionManager"/>
<!--单点登陆的配置代码开始-->
<property name="authenticator.authenticationListeners">
<list>
<ref bean="securityService"/>
</list>
</property>
<!--单点登陆代码结束-->
</bean>


<bean id="sessionManager" class="org.apache.shiro.web.session.mgt.DefaultWebSessionManager">
<property name="sessionValidationInterval" value="60000"/>
<property name="globalSessionTimeout" value="300000"/>
</bean>

<!-- 配置使用自定义认证器,可以实现多Realm认证,并且可以指定特定Realm处理特定类型的验证 -->
<!--<bean id="authenticator" class="im.lsn.oss.exhibition.shiro.CustomizedModularRealmAuthenticator">-->
<!--&lt;!&ndash; 配置认证策略,只要有一个Realm认证成功即可,并且返回所有认证成功信息 &ndash;&gt;-->
<!--<property name="authenticationStrategy">-->
<!--<bean class="org.apache.shiro.authc.pam.AtLeastOneSuccessfulStrategy"></bean>-->
<!--</property>-->
<!--</bean>-->


<!--<bean id="frontSecurityService" class="im.lsn.oss.exhibition.service.FrontSecurityService">-->
<!--&lt;!&ndash; 配置密码匹配器 &ndash;&gt;-->
<!--<property name="credentialsMatcher">-->
<!--<bean class="org.apache.shiro.authc.credential.HashedCredentialsMatcher">-->
<!--&lt;!&ndash; 加密算法为MD5 &ndash;&gt;-->
<!--<property name="hashAlgorithmName" value="MD5"></property>-->
<!--&lt;!&ndash; 加密次数 &ndash;&gt;-->
<!--<property name="hashIterations" value="1024"></property>-->
<!--</bean>-->
<!--</property>-->
<!--</bean>-->

<bean id="formAuthenticationTenantFilter" class="im.lsn.oss.exhibition.web.admin.Security.AdminFilter"/>
<bean id="frontFilter" class="im.lsn.oss.exhibition.web.front.Security.FrontFilter"/> <bean id="authShiroFilter" class="im.lsn.oss.exhibition.web.filter.AuthShiroFilter"/> <bean id="logout" class="im.lsn.oss.exhibition.web.MyLogoutFilter"> <property name="redirectUrl" value="/jsp/login.jsp"/> <property name="frontRedirectUrl" value="/front/index.do"/> </bean> <bean id="shiroSecurityFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean"> <property name="securityManager" ref="securityManager"/> <property name="loginUrl" value="/jsp/login.jsp"/> <property name="successUrl" value="/jsp/login_success.jsp"/> <property name="filters"> <map> <entry key="authc" value-ref="formAuthenticationTenantFilter"/> <entry key="rolesor" value-ref="authShiroFilter"/> <entry key="logout" value-ref="logout"/> <entry key="front" value-ref="frontFilter"/> </map> </property> <property name="filterChainDefinitions"> <value> /jsp/login.jsp = authc /logout = logout <!--/f/logout = logout--> <!--/jsp/front/user_login.jsp = front--> <!--/front/visitor/user/*= front--> <!--/front/visitor/user_favorites.do=front--> /admin/index.do = rolesor[admin,operator_admin,venue_admin,organizer_admin,exhibitors_admin] /admin/organizer/exhibitorInfoListing.do = rolesor[admin,operator_admin,venue_admin,organizer_admin] /admin/organizer/exhibitorInfoList.do = rolesor[admin,operator_admin,venue_admin,organizer_admin] /admin/organizer/verify.do = rolesor[admin,operator_admin,venue_admin,organizer_admin] /admin/organizer/save_verify.do = rolesor[admin,operator_admin,venue_admin] /admin/organizer/exhibitor_info_index.do = rolesor[admin,operator_admin,venue_admin,organizer_admin] /admin/organizer/fail_exhibitorInfoList.do = rolesor[admin,operator_admin,venue_admin,organizer_admin] /admin/organizer/hotRecommend.do = rolesor[admin,operator_admin,venue_admin] /admin/organizer/identifierList.do = rolesor[admin,operator_admin,venue_admin,organizer_admin] /admin/exhibitors/wait_index.do = rolesor[admin,operator_admin,organizer_admin,exhibitors_admin] /admin/exhibitors/booth_index.do = rolesor[admin,operator_admin,organizer_admin,exhibitors_admin] /admin/exhibitors/fail_index.do = rolesor[admin,operator_admin,organizer_admin,exhibitors_admin] /admin/exhibitors/booth_preview.do = rolesor[admin,operator_admin,organizer_admin,exhibitors_admin] /admin/exhibitors/mark.do = rolesor[admin,operator_admin,organizer_admin,exhibitors_admin] /admin/exhibitors/save_mark.do = rolesor[admin,operator_admin,organizer_admin] /admin/exhibitors/edit_booth_venue_branch.do = rolesor[admin,operator_admin,organizer_admin,exhibitors_admin] /admin/exhibitors/wait_product.do = rolesor[admin,operator_admin,organizer_admin,exhibitors_admin] /admin/exhibitors/product_index.do = rolesor[admin,operator_admin,organizer_admin,exhibitors_admin] /admin/exhibitors/fail_product.do = rolesor[admin,operator_admin,organizer_admin,exhibitors_admin] /admin/exhibitors/product_preview.do = rolesor[admin,operator_admin,organizer_admin,exhibitors_admin] /admin/exhibitors/ProductHotRecommend.do = rolesor[admin,operator_admin,organizer_admin] /admin/information/** = rolesor[admin,operator_admin] /admin/log/** = rolesor[admin,operator_admin] /admin/user/** = rolesor[admin,operator_admin,venue_admin,organizer_admin,exhibitors_admin] /admin/user/index.do = rolesor[admin,operator_admin] /admin/venue/** = rolesor[admin,operator_admin,venue_admin] /admin/organizer/** = rolesor[admin,venue_admin,organizer_admin] /admin/exhibitors/** = rolesor[admin,organizer_admin,exhibitors_admin] /admin/venue/index.do = rolesor[admin,operator_admin] /admin/organizer/index.do = rolesor[admin,venue_admin] /admin/operator/edit.do = rolesor[admin,operator_admin] /admin/** = rolesor[admin] </value> </property>
</bean></beans>
 

2.security

import im.lsn.framework.BusinessLogicException;
import im.lsn.framework.jpa.JpaRepositoryImpl;
import im.lsn.framework.shrio.CustomSecurityException;
import im.lsn.oss.exhibition.entity.*;
import im.lsn.oss.exhibition.entity.enumerate.LoginType;
import im.lsn.oss.exhibition.entity.enumerate.VistorType;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.*;
import org.apache.shiro.authc.credential.HashedCredentialsMatcher;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.session.Session;
import org.apache.shiro.session.mgt.DefaultSessionManager;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.subject.Subject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.event.ContextRefreshedEvent;
import org.springframework.context.event.EventListener;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;
import org.springframework.util.DigestUtils;

import javax.annotation.PostConstruct;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import java.util.Collection;
import java.util.Date;

/**
 * Created by fireflyc on 2017/4/26.
 */
@Service
@Transactional
public class SecurityService extends AuthorizingRealm implements AuthenticationListener{
    private Logger LOGGER = LoggerFactory.getLogger(SecurityService.class);

    @Autowired
    UserService userService;
    @Autowired
    private ClickedCountService clickedCountService;

    @Autowired
    private DefaultSessionManager sessionManager;

    @PersistenceContext
    protected EntityManager entityManager;
    private JpaRepositoryImpl<TbUser, Long> userRepository;
    private JpaRepositoryImpl<TbRole, Long> roleRepository;
    private JpaRepositoryImpl<TbUserState, Long> userStateLongJpaRepository;
    private JpaRepositoryImpl<TbType, Long> typeLongJpaRepository;
    private JpaRepositoryImpl<TbExhibitionUser, Long> exhibitionUserLongJpaRepository;

    @PostConstruct
    public void initSecurityService() {
        this.userRepository = new JpaRepositoryImpl<TbUser, Long>(TbUser.class, entityManager);
        this.roleRepository = new JpaRepositoryImpl<TbRole, Long>(TbRole.class, entityManager);
        this.userStateLongJpaRepository = new JpaRepositoryImpl<TbUserState, Long>(TbUserState.class, entityManager);
        this.exhibitionUserLongJpaRepository = new JpaRepositoryImpl<TbExhibitionUser, Long>(TbExhibitionUser.class, entityManager);

        this.typeLongJpaRepository = new JpaRepositoryImpl<TbType, Long>(TbType.class, entityManager);
        HashedCredentialsMatcher matcher = new HashedCredentialsMatcher("MD5");
        setCredentialsMatcher(matcher);
    }

    @EventListener
    public void createAdminAccount(ContextRefreshedEvent event) {
        TbRole role = roleRepository.findOne(QTbRole.tbRole.id.eq(1L));
        if (role == null) {
            role = new TbRole();
            role.setRoleName("系统管理员");
            role.setRoleCnName("admin");
            roleRepository.save(role);
            LOGGER.info("创建系统管理员角色");
        }

        TbUser user = userRepository.findOne(QTbUser.tbUser.id.eq(1L));
        TbUserState userState = userStateLongJpaRepository.findOne(1L);
        TbType type = typeLongJpaRepository.findOne(1L);
        if (user == null) {
            user = new TbUser();
            user.setId(1L);
            user.setCreateTime(new Date());
            user.setRole(role);
            user.setUsername("admin_tontron");
            user.setNickname("系统管理员");
            String password = "admin_tontron" + DigestUtils.md5DigestAsHex("Tontron1169".getBytes());
            user.setPassword(password);
            user.setState(userState);
            user.setType(type);
            userRepository.save(user);
            LOGGER.info("创建系统管理员");
        }
    }

    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
        UserLoginToken userToken = (UserLoginToken) principals.getPrimaryPrincipal();
        SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo();
        if (userToken.getType().equals(LoginType.ADMIN.toString())) {
            authorizationInfo.addRole(userToken.getRole().getRoleName());
        } else {
            authorizationInfo.addRole(userToken.getFrontRole());
        }
        return authorizationInfo;
    }

    public void logout() {
        SecurityUtils.getSubject().logout();
    }

    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authcToken) throws AuthenticationException {
        if (authcToken instanceof UsernamePasswordToken) {
            CustomizedToken token = (CustomizedToken) authcToken;
            if (token.getLoginType().equals(LoginType.ADMIN.toString())) {
                try {
                    QTbUser qUser = QTbUser.tbUser;
                    TbUser user = userRepository.findOne(qUser.username.eq(token.getUsername()));
                    TbUserState userState = userStateLongJpaRepository.findOne(2L);
                    if (user == null) {
                        throw new UnknownAccountException();
                    }
                    if (user.getState().getStateName().equals(userState.getStateName())) {
                        throw new BusinessLogicException("账号被禁用,无法登录");
                    }
                    if(null != user.getClickedCount() && 5<user.getClickedCount()){
                        Integer count = user.getClickedCount();
                        count++;
                        clickedCountService.updateClickedCount(user.getId(),count);
                        throw new BusinessLogicException("登陆失败次数过多,请明天再尝试");
                    }
                    LOGGER.info("用户{} 存在", user.getNickname());
                    String showName = user.getNickname();
                    if (null == showName || showName.length() == 0) {
                        showName = userService.searchShowNameForUser(user);
                    }
                    UserLoginToken loginToken = new UserLoginToken();
                    loginToken.setUserId(user.getId());
                    loginToken.setUserName(user.getUsername());
                    loginToken.setNickName(user.getNickname());
                    loginToken.setRole(user.getRole());
                    loginToken.setShowName(showName);
                    loginToken.setType(token.getLoginType());
                    loginToken.setSubUser(user.getSubUser());
                    return new SimpleAuthenticationInfo(loginToken,
                            user.getPassword(), getName());
                } catch (BusinessLogicException e) {
                    throw new CustomSecurityException(e.getMessage());
                } catch (Exception e) {
                    LOGGER.error(e.getMessage(), e);
                    if (e instanceof UnknownAccountException) {
                        throw new UnknownAccountException();
                    } else {
                        throw new CustomSecurityException("用户名或密码错误");
                    }

                }
            } else {
                try {
                    QTbExhibitionUser qTbExhibitionUser = QTbExhibitionUser.tbExhibitionUser;
                    TbExhibitionUser exhibitionUser = exhibitionUserLongJpaRepository.findOne(qTbExhibitionUser.phone.eq(token.getUsername()));

                    if (exhibitionUser == null) {
                        throw new UnknownAccountException();
                    }
                    LOGGER.info("用户{} 存在", exhibitionUser.getPhone());
                    UserLoginToken loginToken = new UserLoginToken();
                    loginToken.setUserId(exhibitionUser.getId());
                    loginToken.setUserName(exhibitionUser.getPhone());
                    loginToken.setFrontRole(VistorType.EXHIBITOR_USER.getName());
                    loginToken.setShowName(exhibitionUser.getPhone());
                    loginToken.setType(token.getLoginType());
                    return new SimpleAuthenticationInfo(loginToken,
                            exhibitionUser.getPassword(), getName());
                } catch (BusinessLogicException e) {
                    throw new CustomSecurityException(e.getMessage());
                } catch (Exception e) {
                    LOGGER.error(e.getMessage(), e);
                    throw new CustomSecurityException("用户名或密码错误");
                }

            }

        }
        return null;
    }


    public UserLoginToken getLoginToken() {
        try {
            Subject subject = SecurityUtils.getSubject();
            if (subject == null) {
                return null;
            }
            return (UserLoginToken) subject.getPrincipal();
        } catch (Exception e) {
            LOGGER.error(e.getMessage(), e);
            return null;
        }
    }

    public TbUser getLoginUser() {
        UserLoginToken loginToken = getLoginToken();
        Assert.notNull(loginToken);
        TbUser tbUser = userRepository.selectFrom(QTbUser.tbUser)
                .where(QTbUser.tbUser.id.eq(loginToken.getUserId())).fetchOne();
        return tbUser;
    }


    public TbExhibitionUser getFrontLoginUser() {
        UserLoginToken loginToken = getLoginToken();
        Assert.notNull(loginToken);
        TbExhibitionUser exhibitionUser = exhibitionUserLongJpaRepository.selectFrom(QTbExhibitionUser.tbExhibitionUser)
                .where(QTbExhibitionUser.tbExhibitionUser.id.eq(loginToken.getUserId())).fetchOne();
        return exhibitionUser;
    }

//单点登陆的java代码
    public void onSuccess(AuthenticationToken token, AuthenticationInfo info){
        Subject subject = SecurityUtils.getSubject();
        UsernamePasswordToken loginToken = (UsernamePasswordToken) token;
        Collection<Session> sessions = sessionManager.getSessionDAO().getActiveSessions();
        for (Session session : sessions) {
            Subject sub = new Subject.Builder().session(session).buildSubject();
            if (sub.isAuthenticated()) {
                UserLoginToken other = (UserLoginToken) sub.getPrincipal();
                if (other.getUserName().equals(loginToken.getUsername())) {
                    if (!session.getId().equals(subject.getSession().getId())) {
                        session.stop();
                    }
                }
            }
        }
    }

    public void onFailure(AuthenticationToken var1, AuthenticationException var2){

    }

    public void onLogout(PrincipalCollection var1){

    }
//单点登陆的java代码结束
}
原文地址:https://www.cnblogs.com/ly-lyq/p/9987433.html