SpringBoot2 +vue2 + shiro 集成山东通 auth2 方式单点登陆

本文介绍了如何在SpringBoot2项目中结合Vue2和Shiro实现与山东通Auth2的单点登录功能。详细讲述了配置步骤,包括后台的SpringBoot2配置,如SdtSsoToken、SdtSsoRealm的实现,前端Vue2的SSOLogin.vue组件设置,以及Nginx和前置机端口转发的配置。特别提到了配置过程中遇到的坑,如不要在SdtSsoToken中使用Lombok注解,以及在Shiro配置中放开特定路径等。
摘要由CSDN通过智能技术生成

1.前言:

最近在做一个基于SpringBoot 2 + shiro +vue2 项目集成山东通采用Auth2 的方式进行单点登陆。里面很多坑,在此总结记录一下,方便以后查阅。

应用服务器互联网区、山东通接口在政务外网区、前置机在政务外网区,可以访问应用服务器。需要在前置机上配置端口转发。

单点登陆流程:
在这里插入图片描述

在这里插入图片描述
用户通过山东通客户端访问系统。
1、应用系统调用6.3获取授权码(code)接口获取用户访问临时授权码;
2、应用系统调用6.2获取令牌(token)接口获取应用访问令牌;
3、应用系统使用6.2获取的访问令牌和6.3获取的授权码获取统一用户编码,接口对应的是6.4获取登录用户统一用户编码接口;
4、应用系统使用6.4获取的统一用户编码调用6.5获取用户信息接口获取用户的详细信息(包括手机号码)
6、应用系统使用6.5获取的用户手机号码调用手机号码登录接口实现用户登录;

2.配置步骤

2.1 SpringBoot2 后台配置

1. 新增SdtSsoToken 实现AuthenticationToken

package com.dechnic.omsdc.server.admin.shiro.sdtSso;/**
 * @className: SdtSsoToken
 * @author: houqd
 * @date: 2022/11/8
 **/

import lombok.*;
import org.apache.shiro.authc.AuthenticationToken;

/**
 *@description:
 *@author:houqd
 *@time: 2022/11/8 13:40
 *
 */
//@Data
//@AllArgsConstructor
//@RequiredArgsConstructor
//@NoArgsConstructor
public class SdtSsoToken implements AuthenticationToken {
   
//    @NonNull
    private String code;
//    @NonNull
    private String accessToken;

    private String principal;

    public SdtSsoToken( String code,  String accessToken) {
   
        this.code = code;
        this.accessToken = accessToken;
    }

    public String getCode() {
   
        return code;
    }

    public String getAccessToken() {
   
        return accessToken;
    }

    @Override
    public Object getPrincipal() {
   
        return principal;
    }

    public void setPrincipal(String principal) {
   
        this.principal = principal;
    }

    @Override
    public Object getCredentials() {
   
        return code;
    }
}

必坑1: 此处不要使用lombok 注解,使用后登陆验证的时候principle 为null ,验证失败。

2. 新增 SdtSsoRealm 继承 AuthorizingRealm

package com.dechnic.omsdc.server.admin.shiro.sdtSso;/**
 * @className: SdtSsoRealm
 * @author: houqd
 * @date: 2022/11/8
 **/

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.dechnic.omsdc.server.admin.entity.TSysPerm;
import com.dechnic.omsdc.server.admin.entity.TSysRole;
import com.dechnic.omsdc.server.admin.entity.TSysUser;
import com.dechnic.omsdc.server.admin.service.TSysRoleService;
import com.dechnic.omsdc.server.admin.service.TSysUserService;
import com.dechnic.omsdc.server.common.entity.SsoUserBind;
import com.dechnic.omsdc.server.common.mapper.SsoUserBindMapper;
import com.dechnic.omsdc.server.common.service.ISdtSsoApiService;
import com.dechnic.omsdc.server.common.utils.LightWeightEncoder;
import com.dechnic.omsdc.server.common.utils.SpringContextUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.utils.URIBuilder;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
import org.apache.shiro.authc.*;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.springframework.beans.factory.annotation.Autowired;

import javax.annotation.Resource;
import java.util.List;

/**
 *@description:
 *@author:houqd
 *@time: 2022/11/8 13:52
 *
 */
@Slf4j
public class SdtSsoRealm extends AuthorizingRealm {
   
    private static final String DEFAULT_CHARSET = "UTF-8";

    @Autowired
    private SdtSsoConfigProps sdtSsoConfigProps;
    @Autowired
    TSysUserService tSysUserService;
    @Resource
    SsoUserBindMapper ssoUserBindMapper;
    @Autowired
    private TSysRoleService roleService;
    @Autowired
    private ISdtSsoApiService sdtSsoApiService;

    @Override
    public boolean supports(AuthenticationToken token) {
   
        return token instanceof SdtSsoToken;
    }

    // 获取授权信息
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
   
        SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo();
        TSysUser user = (TSysUser) principals.getPrimaryPrincipal();
        List<TSysRole> roleList = user.getRoleList();
        if (roleList == null || roleList.size() == 0) {
   
            roleList = roleService.getUserRoleInfo(user.getId(), TSysPerm.PERM_TYPE.MENU);
            if(roleList == null || roleList.size()==0){
   
                throw new AuthenticationException(user.getUserName()+"尚未分配角色,请联系管理员!");
            }
            user.setRoleList(roleList);
        }

        for (TSysRole role : roleList) {
   
            authorizationInfo.addRole(role.getRoleName());
            for (TSysPerm perm : role.getPermList()) {
   
                if (StringUtils.isNotEmpty(perm.getPermName())) {
   
                    authorizationInfo.addStringPermission(perm.getPermName());
                }
            }
        }
        return authorizationInfo;
    }

    // 获取身份验证相关信息
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
   
        SdtSsoToken sdtSsoToken = (SdtSsoToken) token;
        String accessToken = sdtSsoToken.getAccessToken();
        String code = sdtSsoToken.getCode();
        String ssoUserId = this.sdtSsoApiService.getSsoUserId(accessToken, code);
        String ssoUserPhoneNo = this.sdtSsoApiService.getSsoUserPhoneNo(accessToken, ssoUserId);
        TSysUser user = getTsysUserBySsoUserId(ssoUserPhoneNo);

        List<TSysRole> roleList = user.getRoleList();
        if (roleList == null || roleList.size() == 0) {
   
            roleList = roleService.getUserRoleInfo(user.getId(), TSysPerm.PERM_TYPE.MENU);
            if(roleList == null || roleList.size()==0){
   
                throw new AuthenticationException(user.getUserName()+"尚未分配角色,请联系管理员!");
            }
            user.setRoleList(roleList);
        }
        if (user == null) {
   
            throw new UnknownAccountException("用户名或密码错误!");
        }
        if (user.getState() == TSysUser.STATE.INVALID) {
    // 账户冻结
            throw new LockedAccountException("账号已被锁定,请联系管理员");
        }
        SimpleAuthenticationInfo authenticationInfo =
                new SimpleAuthenticationInfo(user, code, getName());
        return authenticationInfo;
    }



    private TSysUser getTsysUserBySsoUserId(String ssoUserID) {
   
        TSysUser user = null;
        SsoUserBind ssoUserBind = ssoUserBindMapper.selectBySSoUserId(ssoUserID);
        if (ssoUserBind != null){
   
            user = this.tSysUserService.selectById(ssoUserBind.getOmdsUserId());
            List<TSysRole> roleList = user.getRoleList();
            if (roleList == null || roleList.size() == 0) {
   
                roleList = roleService.getUserRoleInfo(user.getId(), TSysPerm.PERM_TYPE.MENU);
                user.setRoleList(roleList);
            }
        }
        return user;
    }
}

3. ShiroConfig 配置

package com.dechnic.omsdc.server.admin.shiro;

import com.dechnic.omsdc.server.admin.shiro.oauth2.client.OAuth2Realm;
import com.dechnic.omsdc.server.admin.shiro.sdtSso.SdtSsoRealm;
import com.dechnic.omsdc.server.admin.shiro.sdtSso.SdtSsoToken;
import com.dechnic.omsdc.server.admin.shiro.zyoaSso.ZyoaSsoRealm;
import com.dechnic.omsdc.server.common.utils.SpringContextUtil;
import lombok.extern.slf4j.Slf4j;
import net.sf.ehcache.CacheManager;
import org.apache.shiro.authc.credential.HashedCredentialsMatcher;
import org.apache.shiro.authc.pam.AtLeastOneSuccessfulStrategy;
import org.apache.shiro.authc.pam.ModularRealmAuthenticator;
import org.apache.shiro.cache.CacheException;
import org.apache.shiro.cache.ehcache.EhCacheManager;
import org.apache.shiro.io.ResourceUtils;
import org.apache.shiro.mgt.SecurityManager;
import org.apache.shiro.mgt.SessionsSecurityManager;
import org.apache.shiro.realm.Realm;
import org.apache.shiro.session.mgt.ExecutorServiceSessionValidationScheduler;
import org.apache.shiro.session.mgt.SessionManager;
import org.apache.shiro.session.mgt.eis.SessionDAO;
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.mgt.CookieRememberMeManager;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.apache.shiro.web.servlet.SimpleCookie;
import org.apache.shiro.web.session.mgt.DefaultWebSessionManager;
import org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.DependsOn;
import org.springframework.web.filter.DelegatingFilterProxy;
import org.springframework.web.servlet.HandlerExceptionResolver;

import javax.servlet.Filter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

@Configuration
@Slf4j
public class ShiroConfig {
   
  private static long globalSessionTimeOut = -1000L;
  @Value("${prop.clientAddress}")
  private String clientAddress;
  /**
   * @description:@RequiresPermissions这类shiro权限的注解, 是DefaultAdvisorAutoProxyCreator这个bean设置之后才会生效的
   * @params:
   * @return:
   * @author: houqd
   * @time: 2020/1/30 17:20
   */
  @Bean
  public static DefaultAdvisorAutoProxyCreator getDefaultAdvisorAutoProxyCreator() {
   
    DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator =
            new DefaultAdvisorAutoProxyCreator();
    defaultAdvisorAutoProxyCreator.setProxyTargetClass(true);
    defaultAdvisorAutoProxyCreator.setUsePrefix(true);
    return defaultAdvisorAutoProxyCreator;
  }

  /**
   * 开启shiro aop注解支持. 使用代理方式;所以需要开启代码支持;
   *
   * @param securityManager
   * @return
   */
  @Bean
  public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(SecurityManager securityManager) {
   
    AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor =
            new AuthorizationAttributeSourceAdvisor();
    authorizationAttributeSourceAdvisor.setSecurityManager(securityManager);
    return authorizationAttributeSourceAdvisor;
  }
  /**
   * 自定义安全域,用户验证、权限等数据在此提供
   *
   * @return
   */

  @Bean
  public RealmUserName myShiroRealm() {
   
    RealmUserName realmUserName = new RealmUserName();
    realmUserName.setCredentialsMatcher(hashedCredentialsMatcher());
    return realmUserName;
  }

  /**
   * 单点登陆realm
   *
   * @return
   */
  @Bean
  public OAuth2Realm oAuth2Realm() {
   
    OAuth2Realm oA
  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值