天天看點

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

大家有問題可以評論區問我,有好的想法也可以評論區提出來,如果對您有用,幫忙點個贊,謝謝啦!