0


若依ruoyi框架实现单点登录或者接入统一认证

目录

1、业务场景

若依的自带的登录功能是成熟的,但是如果要接入上级应用的统一认证(单点登录)的话,还是需要改造一下,改造的主要目的是取消验证码可以自动登录,实现的思想网上有很多都一样,本文讲一下实践(可以测试通过的那种),最终浏览器输入GET请求就可以实现.

2、前端改造

2.1、新增login_sso.vue

/src/view/

下新增login_sso.vue文件作为自动登录的前端入口.
如果你参考别的示例,可能第一步就卡住了,因为你的若依版本很有可能在

/src/view/

目录下不支持驼峰命名

.vue

文件,所以很有可能导致第二步的时候注册不了组件.

<template><div></div></template><script>import{getInfo}from"@/api/login";exportdefault{name:"LoginSso",data(){return{loginRules:{},loading:false,//验证码开关captchaOnOff:true,//注册开关register:false,//重定向redirect:undefined};},watch:{},created(){//页面初始化时调单点登录方法this.loginSso();},methods:{loginSso(){//获取地址栏中的codeconst code =this.$route.query.code;
      console.log("code="+code)//调用登录的接口if(code==''||code==undefined||code==null){//请求中不带code,拦截为正常登录}else{this.loading =true;//开启过渡动画const loginInfo ={"code": code
        };//执行另一套登录操作//不是本系统的用户,去J平台登陆去this.$store.dispatch("LoginSso", loginInfo).then(()=>{this.$message.success("登录成功");this.loading =false;//判断当前角色getInfo().then((res)=>{//获取角色名称var rolesName = res.roles[0];//获取所属场馆this.deptInfo = res.dept;
            sessionStorage.setItem("ssUserName", res.user.nickName);//处理登录this.$router.push({path:this.redirect ||"/"}).catch(()=>{});});}).catch(err=>{
          console.log("有异常信息",err);this.loading =false;});}},}};</script><stylerel="stylesheet/scss"lang="scss"></style>

2.2、index.js注册路由

// 公共路由exportconst constantRoutes =[//...{path:'/login',component:()=>import('@/views/login'),hidden:true},//注册单点登录页面{path:'/loginSso',component:()=>import('@/views/login_sso'),hidden:true},//...

2.3、permission.js增加白名单过滤

//增加单点登录白名单const whiteList =['/login','/auth-redirect','/bind','/register','/loginSso']

2.4、login.js增加后端登录接口

后端将提供无验证码的登录接口

//单点登录 无验证码登录exportfunctionloginSso(queryParam){returnrequest({url:'/loginSso',method:'post',params: queryParam
  })}

2.5、user.js增加单点登录方法

切记注意一下文件顶部的

import

,有可能引入的组件内的其他方法没有引入会导致方法

undefined

.

import{login, logout, getInfo, loginSso}from'@/api/login'import{ getToken, setToken, removeToken }from'@/utils/auth'//...actions:{//...//单点登录LoginSso({commit}, userInfo){const code = userInfo.code;const queryParams ={'code': code
      };returnnewPromise((resolve, reject)=>{loginSso(queryParams).then(res=>{setToken(res.token)commit('SET_TOKEN', res.token)resolve()}).catch(error=>{reject(error)})})}//...}

3、后端改造

3.1、引入依赖

<!-- https://mvnrepository.com/artifact/org.jodd/jodd-http --><dependency><groupId>org.jodd</groupId><artifactId>jodd-http</artifactId><version>6.3.0</version></dependency>

3.2、新增LoginSsoController单点登录控制器

packagecom.ruoyi.web.controller.system;importcom.alibaba.fastjson.JSONObject;importcom.ruoyi.common.constant.Constants;importcom.ruoyi.common.constant.UserConstants;importcom.ruoyi.common.core.domain.AjaxResult;importcom.ruoyi.common.core.domain.entity.SysUser;importcom.ruoyi.common.utils.SecurityUtils;importcom.ruoyi.framework.web.service.SysLoginService;importcom.ruoyi.system.service.ISysUserService;importjodd.http.HttpRequest;importjodd.http.HttpResponse;importlombok.extern.slf4j.Slf4j;importorg.springframework.beans.factory.annotation.Autowired;importorg.springframework.http.HttpHeaders;importorg.springframework.web.bind.annotation.PostMapping;importorg.springframework.web.bind.annotation.RestController;importjava.util.Date;/**
 * 单点登录Controller
 * @author sgc
 */@Slf4j@RestControllerpublicclassLoginSsoController{@AutowiredprivateISysUserService userService;@AutowiredprivateSysLoginService loginService;@PostMapping("/loginSso")publicAjaxResultloginSso(String token){//这里进行单点登录上级系统的令牌校验 写自己的逻辑JSONObject ssoObject =this.checkSsoToken(token);//处理结果 {code=xxx,data={xxx},msg=xxx}String code = ssoObject.getString("code");String loginName =null;AjaxResult ajax =null;if(code.equals("0")){//验证成功需要自动登录JSONObject dataObject = ssoObject.getJSONObject("data");//拿到登录名
            loginName = dataObject.getString("userName");}else{//验证失败返回失败信息
            ajax =AjaxResult.error(ssoObject.getString("msg"));return ajax;}//组装checkUserNameUnique方法需要的SysUser对象,检测用户名存在否SysUser loginUser =newSysUser();
        loginUser.setUserName(loginName);if(UserConstants.NOT_UNIQUE.equals(userService.checkUserNameUnique(loginUser))){
            log.info("单点登录用户[{}]已存在.", loginName);}else{
            log.info("单点登录用户[{}]不存在, 需要创建.", loginName);//将上级系统带过来的用户创建个新用户存储起来SysUser sysUser =this.createSsoUser(ssoObject);
            userService.insertUser(sysUser);}//生成本系统的令牌给到前端进行登录
        ajax =AjaxResult.success();//这里设置单点登录用户默认密码为123456String tokenNew = loginService.loginNoCaptcha(loginName,"123456",null);
        ajax.put("token", tokenNew);
        ajax.put("msg","登录成功");return ajax;}//处理父级系统传过来的令牌进行校验返回登录信息结果JSONObjectcheckSsoToken(String token){JSONObject jsonObject =newJSONObject();//测试代码
        jsonObject.put("code","0");
        jsonObject.put("msg","验证成功");JSONObject jsonObjectData =newJSONObject();
        jsonObjectData.put("userName","sso1");
        jsonObjectData.put("nickName","单点1");
        jsonObject.put("data",jsonObjectData);//测试环境String baseUrl ="http://xxxxx/xxx/check?code="+ token;//根据实际地址进行修改//...//进行逻辑校验...//...return jsonObject;}//组装单点登录的用户对象 将来存入本系统SysUsercreateSsoUser(JSONObject ssoObject){JSONObject dataObject = ssoObject.getJSONObject("data");//从父级系统拿到的用户信息String userId = dataObject.getString("userId");String companyId = dataObject.getString("companyId");String companyName = dataObject.getString("companyName");String deptId = dataObject.getString("deptId");String userName = dataObject.getString("userName");String nickName = dataObject.getString("nickName");String email = dataObject.getString("email");String phonenumber = dataObject.getString("phonenumber");String sex = dataObject.getString("sex");String avatar = dataObject.getString("avatar");//组装本系统用户信息SysUser sysUser =newSysUser();
        sysUser.setUserName(userName);
        sysUser.setNickName(nickName);
        sysUser.setPassword(SecurityUtils.encryptPassword("123456"));
        sysUser.setCreateBy("sso");
        sysUser.setCreateTime(newDate());
        sysUser.setDeptId(202L);//所属部门 建议在后管新增一个部门进行初始化Long[] roleIds ={100L};
        sysUser.setRoleIds(roleIds);//归属角色  建议在后管新增一个角色进行初始化return sysUser;}}

3.3、增加单点登录后端方法

com.ruoyi.framework.web.service.SysLoginService

中增加一个无验证码登录的方法

loginNoCaptcha

.

/**
 * 无需验证码登录
 * 重写login方法将验证码模块去掉
 * @param username
 * @param password
 * @param uuid
 * @return
 */publicStringloginNoCaptcha(String username,String password,String uuid){// 用户验证Authentication authentication =null;try{UsernamePasswordAuthenticationToken authenticationToken =newUsernamePasswordAuthenticationToken(username, password);AuthenticationContextHolder.setContext(authenticationToken);// 该方法会去调用UserDetailsServiceImpl.loadUserByUsername
        authentication = authenticationManager.authenticate(authenticationToken);}catch(Exception e){if(e instanceofBadCredentialsException){AsyncManager.me().execute(AsyncFactory.recordLogininfor(username,Constants.LOGIN_FAIL,MessageUtils.message("user.password.not.match")));thrownewUserPasswordNotMatchException();}else{AsyncManager.me().execute(AsyncFactory.recordLogininfor(username,Constants.LOGIN_FAIL, e.getMessage()));thrownewServiceException(e.getMessage());}}AsyncManager.me().execute(AsyncFactory.recordLogininfor(username,Constants.LOGIN_SUCCESS,MessageUtils.message("user.login.success")));LoginUser loginUser =(LoginUser) authentication.getPrincipal();recordLoginInfo(loginUser.getUserId());// 生成tokenreturn tokenService.createToken(loginUser);}

3.4、增加shiro白名单

增加后端对于

/loginSso

的放行.

//...// 对于登录login 注册register 验证码captchaImage 允许匿名访问.antMatchers("/login","/register","/captchaImage","/loginSso").permitAll()//...

本文转载自: https://blog.csdn.net/csdn_avatar_2019/article/details/129306927
版权归原作者 市井榴芒 所有, 如有侵权,请联系我们删除。

“若依ruoyi框架实现单点登录或者接入统一认证”的评论:

还没有评论