天天看点

springboot项目前后端一体和前后端分离的整合xxl-sso实现单点登陆springboot项目集成xxl-sso

首先感谢xxl-sso开源项目,传送门 xxl-soo官网.

整合xxl-sso

  • springboot项目集成xxl-sso
    • 前后端一体的项目集成xxl-sso
      • 前后端分离集成xxl-sso

springboot项目集成xxl-sso

前言:由于我们公司项目比较多,登陆基本上都是工号加密码,所以想做一个单点系统,登陆A系统之后就可以直接进入其他任意相关系统无需登陆,一个系统退出,所有系统退出,这里找了很多资料和博客,最终选择xxl-sso做集成

大家把项目下载下来后更xxl-sso-server中的application.properties文件

### web
server.port=8080
server.servlet.context-path=/xxl-sso-server

### resources
spring.mvc.servlet.load-on-startup=0
spring.mvc.static-path-pattern=/static/**
spring.resources.static-locations=classpath:/static/

### freemarker
spring.freemarker.templateLoaderPath=classpath:/templates/
spring.freemarker.suffix=.ftl
spring.freemarker.charset=UTF-8
spring.freemarker.request-context-attribute=request
spring.freemarker.settings.number_format=0.##########

### xxl-sso
xxl.sso.redis.address=redis://127.0.0.1:6379
xxl.sso.redis.expire.minute=1440
           

主要更改一下这个redis的地址即可

他这边还给了两个实例项目xxl-sso-web-sample-springboot和xxl-sso-token-sample-springboot,我这边使用xxl-sso-web-sample-springboot做的测试,先更改application.properties文件

### web
server.port=8082
server.servlet.context-path=/xxl-sso-web-sample-springboot

### resources
spring.mvc.servlet.load-on-startup=0
spring.mvc.static-path-pattern=/static/**
spring.resources.static-locations=classpath:/static/

### freemarker
spring.freemarker.templateLoaderPath=classpath:/templates/
spring.freemarker.suffix=.ftl
spring.freemarker.charset=UTF-8
spring.freemarker.request-context-attribute=request
spring.freemarker.settings.number_format=0.##########

### xxl-sso
xxl.sso.server=http://localhost:8080/xxl-sso-server
xxl.sso.logout.path=/logout
xxl-sso.excluded.paths=
xxl.sso.redis.address=redis://127.0.0.1:6379


           

这里主要更改xxl.sso.server,这个改成你xxl-sso-server的启动地址即可,还需改一下redis地址

这里启动项目一个8080的http://localhost:8080/xxl-sso-server/login,一个8081的http://localhost:8081/xxl-sso-web-sample-springboot

在8080未登陆情况下,8081直接登陆会跳转至8080登陆页面,任意一个系统登陆成功后,同浏览器直接可以输入其他系统地址,无需登陆,一个系统退出,所有系统都退出

springboot项目前后端一体和前后端分离的整合xxl-sso实现单点登陆springboot项目集成xxl-sso
springboot项目前后端一体和前后端分离的整合xxl-sso实现单点登陆springboot项目集成xxl-sso

这里基本上按照dome走就搭建完毕了,接下来进入我们自己的项目

前后端一体的项目集成xxl-sso

上一步中的http://localhost:8081/xxl-sso-web-sample-springboot就是一个springboot项目这里我们集成到自己项目中去

首先添加maven依赖,pom中添加,我这里用到springboot版本是>2.3.0的版本

<dependency>
            <groupId>com.xuxueli</groupId>
            <artifactId>xxl-sso-core</artifactId>
            <version>1.1.0</version>
        </dependency>
           

配置application.properties文件中添加xxl-sso相关配置

xxl.sso.server=http://localhost:8080/xxl-sso-server
xxl.sso.logout.path=/logout
xxl-sso.excluded.paths=
xxl.sso.redis.address=redis://127.0.0.1:6379
           

这里xxl-sso.excluded.paths可以配置无需拦截的一些路径,如文件下载,这种公共对外接口无需登陆的路径,多个用,隔开

添加XxlSsoConfig.java配置类

package com.xxl;

import com.xxl.sso.core.conf.Conf;
import com.xxl.sso.core.filter.XxlSsoWebFilter;
import com.xxl.sso.core.util.JedisUtil;
import org.springframework.beans.factory.DisposableBean;
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;

/**
 * @author xuxueli 2018-11-15
 */
@Configuration
public class XxlSsoConfig implements DisposableBean {


    @Value("${xxl.sso.server}")
    private String xxlSsoServer;

    @Value("${xxl.sso.logout.path}")
    private String xxlSsoLogoutPath;

    @Value("${xxl-sso.excluded.paths}")
    private String xxlSsoExcludedPaths;

    @Value("${xxl.sso.redis.address}")
    private String xxlSsoRedisAddress;


    @Bean
    public FilterRegistrationBean xxlSsoFilterRegistration() {

        // xxl-sso, redis init
        JedisUtil.init(xxlSsoRedisAddress);

        // xxl-sso, filter init
        FilterRegistrationBean registration = new FilterRegistrationBean();

        registration.setName("XxlSsoWebFilter");
        registration.setOrder(1);
        registration.addUrlPatterns("/*");
        registration.setFilter(new XxlSsoWebFilter());
        registration.addInitParameter(Conf.SSO_SERVER, xxlSsoServer);
        registration.addInitParameter(Conf.SSO_LOGOUT_PATH, xxlSsoLogoutPath);
        registration.addInitParameter(Conf.SSO_EXCLUDED_PATHS, xxlSsoExcludedPaths);

        return registration;
    }

    @Override
    public void destroy() throws Exception {

        // xxl-sso, redis close
        JedisUtil.close();
    }

}
           

注意,官方给的模板中用户名密码是写死在后台的,实际我们应用中需要更改为从数据库获取,可以在xxl-sso-server中更改UserServiceImpl,我这边做测试就自己先加了一个用户名密码

springboot项目前后端一体和前后端分离的整合xxl-sso实现单点登陆springboot项目集成xxl-sso

我这边是在控制器里面写了个入口,用重定向做了跳转,跳转到我自己的其他项目的主页,因为这个项目中在session中存了用户信息,所以我这边在这里跳转前进行了存储,因为这里是做演示,我这边在xxl-sso-server存的是写死的用户名和密码,这边获取到后再去数据库根据id把用户信息查询到存储全量信息

@RequestMapping("/")
    public void index(Model model, HttpServletRequest request,HttpServletResponse response) {

        XxlSsoUser xxlUser = (XxlSsoUser) request.getAttribute(Conf.SSO_USER);
        request.getSession().setAttribute(ClomnUtil.USERKEY,loginServiceipml.loginByid(Integer.parseInt(xxlUser.getUserid())));
        String uri = request.getScheme() + "://" +
                request.getServerName() +
                ":" + request.getLocalPort() +"/menu";
        try {
			response.sendRedirect(uri);
		} catch (IOException e) {
				// TODO Auto-generated catch block
			e.printStackTrace();
			
		}
    }
           

上面这一步其实是登陆后做跳转用的,相当于我们输入http://localhost:项目端口/,会直接跳转到8080的xxs-sso中去先登陆,登陆完成后调用我上面的方案去跳转到我的项目主页,加这一步的目的是为了存储我的用户信息到session,方便我后续使用这个用户信息

退出的时候同样,情况我们的session和全局token信息

@GetMapping(value="/loginout")
    @ResponseBody
    public int getLoginPageOut(HttpServletRequest request) {
    	request.getSession().removeAttribute(ClomnUtil.USERKEY);
    	SsoTokenLoginHelper.logout(CookieUtil.getValue(request, "xxl_sso_sessionid"));
    	return 200;
    }
           

这里的返回信息其实没用,因为调用SsoTokenLoginHelper.logout后会自动调用一个重定向方案跳转到的登陆界面

这一套springboot一体的就完成了,基本上改动很小,改一下配置文件,加一个配置类,登陆、退出的时候根据自己的需求去做特殊处理就完了

前后端分离集成xxl-sso

我这边还有个项目是使用vue前后端分离的,刚开始集成的时候一直集成不了,因为涉及到跨域,前后端分离登一大堆问题,好在后来都解决了,下面开始

首先还是一样后端更改application.properties,添加配置类XxlSsoConfig,这里不在重复了,这里说一下我的方案

因为前后端分离的项目,我们前端统一登陆后时没办法直接跳转到VUE的前端页面的,即时跳过去我的相关token也没法给到vue页面,这里统一登陆完成后先进入后端,从后端再跳到登陆页面(也可以是其他空白页面),在这个页面初始化的时候去把相关信息存取到前台的公共变量中,在ajax中去设置统一拦截,请求前去统一加xxl_sso_sessionid和token,一定要加xxl_sso_sessionid不然后台会拦截,但无法跳转到登陆,页面会一直停在这里的,上代码

@RequestMapping("/loginSinge")
	  public void index(Model model, HttpServletRequest request,HttpServletResponse response) {
		 
	        
	        XxlSsoUser xxlUser = (XxlSsoUser) request.getAttribute(Conf.SSO_USER);
	        String xxl_sso_sessionid = CookieUtil.getValue(request, "xxl_sso_sessionid");
    		
	         sysUserTokenService.createToken(Long.parseLong(xxlUser.getUserid()),xxl_sso_sessionid);
	        String uri = request.getScheme() + "://localhost:8001" 
	                +"/login#/login?token="+xxl_sso_sessionid;
	        try {
				response.sendRedirect(uri);
			} catch (IOException e) {
					// TODO Auto-generated catch block
				e.printStackTrace();
				
			}
	    }
	/**
	 * 退出
	 */
	@PostMapping("/sys/logout")
	public R logout(HttpServletRequest request) {
		sysUserTokenService.logout(getUserId());
		SsoTokenLoginHelper.logout(CookieUtil.getValue(request, "token"));
		return R.ok();
	}
           

这里//localhost:8001是前端项目的地址,这里方便演示我就先写死了,这里sysUserTokenService.createToken(Long.parseLong(xxlUser.getUserid()),xxl_sso_sessionid);是我本地生成token的方法,我这边为了偷懒直接用xxl-sso的sessionid作为我的token,这里比较麻烦,如果自己生成的话,后面可以重定向的时候?token="+xxl_sso_sessionid;需要再加一个你自己的token,退出也一样,先清自己的token,再清全局token,清完后会自动跳转到登陆

vue页面前端再created的时候调用this.loginSing()

loginSing () {
        if(this.$route.query.token!=null){
          this.$cookie.set('token', this.$route.query.token)
          this.$router.replace({ name: 'home' })
        }else{
          window.location.href='http://localhost:8080/xxl-sso-server/'
        }
      }
           

这边直接从请求中把token获取到存到前台全局变量中

在httpRequest.js中添加

import Vue from 'vue'
import axios from 'axios'

const http = axios.create({
  timeout: 1000 * 30,
  withCredentials: true,
  headers: {
    'Content-Type': 'application/json; charset=utf-8'
  }
})
/**
 * 请求拦截
 */
http.interceptors.request.use(config => {
  return config
}, error => {
  return Promise.reject(error)
})

           

主要是xxl_sso_sessionid这个全局token带上即可,然后访问统一登陆入口,登陆成功访问我们自己项目的loginSinge方法,会跳登陆页面然后立即跳到首页,这个很快的,我这个方案是把token放到请求路径中,通过 this.$route.query去获取,可能有点不安全,但功能确实是实现了。另外他这个首页和登陆大家也可以根据需求去更改一下,这个样式…也还行吧,路径xxl-sso-server中src/main/resources下templates里面的login.ftl和index.ftl

大家有问题可以评论区问我,有好的想法也可以评论区提出来,如果对您有用,帮忙点个赞,谢谢啦!