• 首页 首页 icon
  • 工具库 工具库 icon
    • IP查询 IP查询 icon
  • 内容库 内容库 icon
    • 快讯库 快讯库 icon
    • 精品库 精品库 icon
    • 问答库 问答库 icon
  • 更多 更多 icon
    • 服务条款 服务条款 icon

若依ruoyi实现单点登录

武飞扬头像
吴里庆庆
帮助1

系统说明(两个系统数据库用户信息username是同步的,都是唯一的)

  1. 第三方平台 
  2. 若依系统(ruoyi分离版)

登录需求:

我登录到第三方平台,第三方平台嵌入我们的若依,所以在跳若依的管理页面时不想再登录了。但是验证是需要把第三方平台的token解析成username,拿到username只走我们自己只验证账号的认证。(默认是用户名 密码)

实现构想:

通过前端新加一个页面没有任何样式,只接收第三方平台传来的token,拿到token请求我们自定义的登录controller解析到对应的用户名,直接走用户名认证,认证成功返回生成的jwtToken。前端的新页面拿到请求成功的jwtToken后直接延用原来登录的逻辑跳转到若依的首页!

待优化:

拿到第三方平台的token可以再请求下第三方的接口验证对方的token是否有效。如果该账号在若依不存在可以在请求第三方时 获取对方的账号部门信息新建一个。(是防止对方传过来的token被多次使用,因为双方token过期时间不一致)

项目目录结构:(给个大概,截图太累了)

学新通

代码实现(全部在若依端进行改造)

  • login.js中添加 (请求后端接口)
  1.  
    export function ywgllogin(data) {
  2.  
    return request({
  3.  
    url: '/ywgllogin',
  4.  
    method: 'post',
  5.  
    data: data
  6.  
    })
  7.  
    }
  • user.js中添加(引用组件,添加方法)

学新通

  1.  
    //ywgl通过它自己的accessToken登录
  2.  
    YwglLogin({ commit }, data) {
  3.  
     
  4.  
    return new Promise((resolve, reject) => {
  5.  
    ywgllogin(data).then(res => {
  6.  
    setToken(res.token)
  7.  
    commit('SET_TOKEN', res.token)
  8.  
    resolve()
  9.  
    }).catch(error => {
  10.  
    reject(error)
  11.  
    })
  12.  
    })
  13.  
    },
  • index.js中添加
  1.  
    {
  2.  
    path: '/ywgllogin',
  3.  
    component: () =>
  4.  
    import ('@/views/ywgllogin'),
  5.  
    hidden: true
  6.  
    },
  • views下面同原来login.vue同级新建ywgllogin.vue
  1.  
    <template>
  2.  
    <div>ywgl跳转登录中...</div>
  3.  
    </template>
  4.  
     
  5.  
    <script>
  6.  
    export default {
  7.  
    name: "YwglLogin",
  8.  
    data() {
  9.  
    return {
  10.  
    loginRules: {},
  11.  
    loginForm: {
  12.  
    username: "",
  13.  
    password: "",
  14.  
    rememberMe: false,
  15.  
    code: "",
  16.  
    uuid: "",
  17.  
    },
  18.  
    loading: false,
  19.  
    // 验证码开关
  20.  
    captchaOnOff: true,
  21.  
    // 注册开关
  22.  
    register: false,
  23.  
    redirect: undefined,
  24.  
    };
  25.  
    },
  26.  
    watch: {
  27.  
    $route: {
  28.  
    handler: function (route) {
  29.  
    this.redirect = route.query && route.query.redirect;
  30.  
    },
  31.  
    immediate: true,
  32.  
    },
  33.  
    },
  34.  
    created() {
  35.  
    //平台单独的登录 2022年4月19日11:23:58
  36.  
    this.getLoginByNameAndTokenJ();
  37.  
    },
  38.  
    methods: {
  39.  
    /**
  40.  
    * 三方平台单点登陆系统 2022年4月19日11:22:33
  41.  
    * 只传递token
  42.  
    */
  43.  
    getLoginByNameAndTokenJ() {
  44.  
    //获取地址栏中的token
  45.  
    var accessToken = this.$route.query.accessToken;
  46.  
    //调用登录的接口
  47.  
    if (accessToken == "" || accessToken == undefined || accessToken == null) {
  48.  
    //不是那边系统过来的,不走这个地方(阻止created的方法继续向下走)
  49.  
    this.$message.error("用户token为空");
  50.  
    } else {
  51.  
    //转圈圈,不要看到登陆页面,无感体验
  52.  
    this.loading = true;
  53.  
    var logininfo = {
  54.  
    accessToken: accessToken,
  55.  
    };
  56.  
     
  57.  
    //执行另一套登录操作
  58.  
    //不是本系统的用户,去J平台登陆去
  59.  
    this.$store
  60.  
    .dispatch("YwglLogin", logininfo)
  61.  
    .then(() => {
  62.  
    //this.$message.success("登录成功");
  63.  
    this.loading = false;
  64.  
    this.$router.push({ path: this.redirect || "/" }).catch(() => {});
  65.  
    })
  66.  
    .catch((err) => {
  67.  
    console.log("有异常信息", err);
  68.  
    //异常信息
  69.  
    this.loading = false;
  70.  
    // if (this.captchaOnOff) {
  71.  
    // this.getCode();
  72.  
    // }
  73.  
    });
  74.  
     
  75.  
     
  76.  
    }
  77.  
    },
  78.  
    },
  79.  
    };
  80.  
    </script>
  81.  
     
  82.  
    <style rel="stylesheet/scss" lang="scss">
  83.  
    </style>
学新通
  •  permission.js添加白名单放行(两处)

const whiteList = ['/ywgllogin','/login', '/auth-redirect', '/bind', '/register']

if (to.path === '/login'||to.path === '/ywgllogin') {
  • 后端登录新接口(controller)
  1.  
    package com.ruoyi.web.controller.system;
  2.  
     
  3.  
    import com.ruoyi.common.constant.Constants;
  4.  
    import com.ruoyi.common.core.domain.AjaxResult;
  5.  
    import com.ruoyi.common.core.domain.model.LoginBody;
  6.  
    import com.ruoyi.common.utils.StringUtils;
  7.  
    import com.ruoyi.framework.web.service.YwglTokenService;
  8.  
    import com.ruoyi.system.service.ISysUserService;
  9.  
    import org.springframework.beans.factory.annotation.Autowired;
  10.  
    import org.springframework.web.bind.annotation.PostMapping;
  11.  
    import org.springframework.web.bind.annotation.RequestBody;
  12.  
    import org.springframework.web.bind.annotation.RestController;
  13.  
     
  14.  
     
  15.  
    /**
  16.  
    * 登录验证
  17.  
    *
  18.  
    * @author qwu
  19.  
    */
  20.  
    @RestController
  21.  
    public class YwglAccessTokenLoginController {
  22.  
     
  23.  
     
  24.  
     
  25.  
    @Autowired
  26.  
    private ISysUserService sysUserService;
  27.  
    @Autowired
  28.  
    private YwglTokenService ywglTokenService;
  29.  
     
  30.  
    /**
  31.  
    * 登录方法
  32.  
    *
  33.  
    * @return 结果
  34.  
    */
  35.  
    @PostMapping("/ywgllogin")
  36.  
    public AjaxResult ywgllogin(@RequestBody LoginBody loginBody) {
  37.  
     
  38.  
    String accessToken = loginBody.getAccessToken();
  39.  
    if (StringUtils.isNotEmpty(accessToken)) {
  40.  
    String tokenNew = ywglTokenService.ywglLogin(accessToken);
  41.  
    AjaxResult ajax = AjaxResult.success();
  42.  
    ajax.put(Constants.TOKEN, tokenNew);
  43.  
    return ajax;
  44.  
     
  45.  
    } else {
  46.  
    return AjaxResult.error();
  47.  
    }
  48.  
     
  49.  
     
  50.  
    }
  51.  
     
  52.  
     
  53.  
    }
学新通
注意:LoginBody新增变量accessToken
  • service添加登录验证走自己的
  1.  
    public String ywglLogin(String accessToken)
  2.  
    {
  3.  
    // 用户验证
  4.  
    Authentication authentication = null;
  5.  
    String username =accessToken;
  6.  
    try
  7.  
    {
  8.  
    username="这里填自己如何解析我们第三方传来的accessToken变成系统的username这里我就省略了";
  9.  
    authentication = authenticationManager
  10.  
    .authenticate(new YwglAuthenticationToken(username));
  11.  
    }
  12.  
    catch (Exception e)
  13.  
    {
  14.  
    if (e instanceof BadCredentialsException)
  15.  
    {
  16.  
    AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_FAIL, MessageUtils.message("user.password.not.match")));
  17.  
    throw new UserPasswordNotMatchException();
  18.  
    }
  19.  
    else
  20.  
    {
  21.  
    AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_FAIL, e.getMessage()));
  22.  
    throw new ServiceException(e.getMessage());
  23.  
    }
  24.  
    }
  25.  
    AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_SUCCESS, MessageUtils.message("user.login.success")));
  26.  
    LoginUser loginUser = (LoginUser) authentication.getPrincipal();
  27.  
    recordLoginInfo(loginUser.getUserId());
  28.  
    // 生成token
  29.  
    return tokenService.createToken(loginUser);
  30.  
    }
学新通
  • 添加自定义认证  YwglAuthenticationToken 
  1.  
    package com.ruoyi.framework.ywglsecurity;
  2.  
     
  3.  
    import org.springframework.security.authentication.AbstractAuthenticationToken;
  4.  
    import org.springframework.security.core.GrantedAuthority;
  5.  
     
  6.  
    import java.util.Collection;
  7.  
     
  8.  
    public class YwglAuthenticationToken extends AbstractAuthenticationToken {
  9.  
     
  10.  
    private final Object principal;
  11.  
     
  12.  
    public YwglAuthenticationToken(Object principal) {
  13.  
    super(null);
  14.  
    this.principal = principal;
  15.  
    this.setAuthenticated(false);
  16.  
    }
  17.  
     
  18.  
    public YwglAuthenticationToken(Object principal, Collection<? extends GrantedAuthority> authorities) {
  19.  
    super(authorities);
  20.  
    this.principal = principal;
  21.  
    super.setAuthenticated(true);
  22.  
    }
  23.  
     
  24.  
    @Override
  25.  
    public Object getCredentials() {
  26.  
    return null;
  27.  
    }
  28.  
     
  29.  
    @Override
  30.  
    public Object getPrincipal() {
  31.  
    return this.principal;
  32.  
    }
  33.  
     
  34.  
    @Override
  35.  
    public void setAuthenticated(boolean isAuthenticated) throws IllegalArgumentException {
  36.  
    if (isAuthenticated) {
  37.  
    throw new IllegalArgumentException(
  38.  
    "Cannot set this token to trusted - use constructor which takes a GrantedAuthority list instead");
  39.  
    }
  40.  
     
  41.  
    super.setAuthenticated(false);
  42.  
    }
  43.  
     
  44.  
    @Override
  45.  
    public void eraseCredentials() {
  46.  
    super.eraseCredentials();
  47.  
    }
  48.  
    }
学新通
  • 添加 YwglAuthenticationProvider   
  1.  
    package com.ruoyi.framework.ywglsecurity;
  2.  
     
  3.  
    import com.ruoyi.framework.web.service.UserDetailsServiceImpl;
  4.  
    import org.springframework.beans.factory.annotation.Autowired;
  5.  
    import org.springframework.security.authentication.AuthenticationProvider;
  6.  
    import org.springframework.security.core.Authentication;
  7.  
    import org.springframework.security.core.AuthenticationException;
  8.  
    import org.springframework.security.core.userdetails.UserDetails;
  9.  
    import org.springframework.stereotype.Component;
  10.  
     
  11.  
    import java.util.Collections;
  12.  
     
  13.  
    @Component
  14.  
    public class YwglAuthenticationProvider implements AuthenticationProvider {
  15.  
    @Autowired
  16.  
    private UserDetailsServiceImpl userDetailsService;
  17.  
     
  18.  
    /**
  19.  
    * 认证逻辑
  20.  
    */
  21.  
    @Override
  22.  
    public Authentication authenticate(Authentication authentication) throws AuthenticationException {
  23.  
    YwglAuthenticationToken ywglAuthenticationToken = (YwglAuthenticationToken) authentication;
  24.  
     
  25.  
    String username = (String) ywglAuthenticationToken.getPrincipal();
  26.  
    UserDetails user = userDetailsService.loadUserByUsername(username);
  27.  
    YwglAuthenticationToken result = new YwglAuthenticationToken(user, Collections.emptyList());
  28.  
    /*
  29.  
    Details 中包含了 ip地址、 sessionId 等等属性 也可以存储一些自己想要放进去的内容
  30.  
    */
  31.  
    result.setDetails(ywglAuthenticationToken.getDetails());
  32.  
    return result;
  33.  
    }
  34.  
     
  35.  
    /**
  36.  
    *UserIdAuthenticationToken交给UserIdAuthenticationProvider处理
  37.  
    * @param aClass
  38.  
    * @return
  39.  
    */
  40.  
    @Override
  41.  
    public boolean supports(Class<?> aClass) {
  42.  
    return YwglAuthenticationToken.class.isAssignableFrom(aClass);
  43.  
     
  44.  
    }
  45.  
    }
学新通
  • 修改SecurityConfig 放行我们的请求登录路径 并把自定义认证加进来
.antMatchers("/hello","/ywgllogin","/login", "/register", "/captchaImage").anonymous()
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception
{
    auth.userDetailsService(userDetailsService).passwordEncoder(bCryptPasswordEncoder());
    auth.authenticationProvider(ywglAuthenticationProvider);
}

主要参考:

这篇好文章是转载于:学新通技术网

  • 版权申明: 本站部分内容来自互联网,仅供学习及演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,请提供相关证据及您的身份证明,我们将在收到邮件后48小时内删除。
  • 本站站名: 学新通技术网
  • 本文地址: /boutique/detail/tanhggakbk
系列文章
更多 icon
同类精品
更多 icon
继续加载