当前位置:网站首页>Our company has used this set of general solutions for 7 years, and has opened up dozens of systems, a stable batch!
Our company has used this set of general solutions for 7 years, and has opened up dozens of systems, a stable batch!
2022-06-30 11:44:00 【Migrant worker brother】
Click below “Java Programming duck ” Follow and mark the stars
More exciting First time direct
Preface
What is single sign on ? Full single sign on name Single Sign On( hereinafter referred to as SSO), Log in to a system in a multi system application group , Can be authorized on all other systems without having to log in again , Including single sign on and single sign off , Pictured ( Nonstandard , It's just easy to understand ).

One 、CAS What is it? ?
CAS yes Yale An open source project initiated by the University , For the purpose of Web The application system provides a reliable single sign on method ,CAS stay 2004 year 12 The month officially became JA-SIG A project for .CAS It has the following characteristics :
Open source enterprise single sign on solution .
CAS Server For those that need to be deployed independently Web application .
CAS Client Support a lot of clients ( This refers to the single sign on system Web application ), Include Java, .Net, PHP, Perl, Apache, uPortal, Ruby etc. .
Two 、 Build client system
1. introduce CAS
Note that the certificate is imported into jdk in , Be sure to be precise cacerts Under this document , Otherwise, it will always be reported that it refuses to write , In addition, it is better to use the command window under the administrator
2. Client backend setup
1. Add dependency
<dependency>
<groupId>org.jasig.cas.client</groupId>
<artifactId>cas-client-core</artifactId>
<version>3.3.2</version>
</dependency>
<dependency>
<groupId>joda-time</groupId>
<artifactId>joda-time</artifactId>
<version>2.10.5</version>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-cas</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-taglibs</artifactId>
</dependency>2. Configure client
server:
port: 12343. add to config(filter) file
All addresses are ip, If you use hosts Mapping address , There may be problems
package com.casclient1.cas.config;
import org.jasig.cas.client.session.SingleSignOutFilter;
import org.jasig.cas.client.util.HttpServletRequestWrapperFilter;
import org.jasig.cas.client.validation.Cas20ProxyReceivingTicketValidationFilter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.annotation.Order;
import org.springframework.web.filter.CharacterEncodingFilter;
import javax.servlet.Filter;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
@Configuration
public class FilterConfig implements Serializable, InitializingBean {
private static final Logger LOGGER = LoggerFactory.getLogger(FilterConfig.class);
public static final String CAS_SIGNOUT_FILTER_NAME = "CAS Single Sign Out Filter";
public static final String CAS_AUTH_FILTER_NAME = "CAS Filter";
public static final String CAS_IGNOREL_SSL_FILTER_NAME = "CAS Ignore SSL Filter";
public static final String CAS_FILTER_NAME = "CAS Validation Filter";
public static final String CAS_WRAPPER_NAME = "CAS HttpServletRequest Wrapper Filter";
public static final String CAS_ASSERTION_NAME = "CAS Assertion Thread Local Filter";
public static final String CHARACTER_ENCODING_NAME = "Character encoding Filter";
//CAS Server exit address
private static String casSigntouServerUrlPrefix = "https://127.0.0.1:8443/cas/logout";
//CAS Server login address
private static String casServerLoginUrl = "https://127.0.0.1:8443/cas/login";
// Client address
private static String clienthosturl="http://127.0.0.1:1234";
//CAS Server address
private static String casValidationServerUrlPrefix = "https://127.0.0.1:8443/cas";
public FilterConfig() {
}
/**
* Single sign out function , Put it in the other filter Before
* casSigntouServerUrlPrefix Prefix logout :https://123.207.122.156:8081/cas/logout
*
* @return
*/
@Bean
@Order(0)
public FilterRegistrationBean getCasSignoutFilterRegistrationBean() {
FilterRegistrationBean registration = new FilterRegistrationBean();
registration.setFilter(getCasSignoutFilter());
registration.addUrlPatterns("/*", "*.html");
registration.addInitParameter("casServerUrlPrefix", casSigntouServerUrlPrefix);
registration.setName(CAS_SIGNOUT_FILTER_NAME);
registration.setEnabled(true);
return registration;
}
@Bean(name = CAS_SIGNOUT_FILTER_NAME)
public Filter getCasSignoutFilter() {
return new SingleSignOutFilter();
}
/**
* Ignore SSL authentication
*
* @return
*/
@Bean
@Order(1)
public FilterRegistrationBean getCasSkipSSLValidationFilterRegistrationBean() {
FilterRegistrationBean registration = new FilterRegistrationBean();
registration.setFilter(getCasSkipSSLValidationFilter());
registration.addUrlPatterns("/*", "*.html");
registration.setName(CAS_IGNOREL_SSL_FILTER_NAME);
registration.setEnabled(true);
return registration;
}
@Bean(name = CAS_IGNOREL_SSL_FILTER_NAME)
public Filter getCasSkipSSLValidationFilter() {
return new IgnoreSSLValidateFilter();
}
/**
* Responsible for user authentication
* casServerLoginUrl:https://123.207.122.156:8081/cas/login
* casServerName:https://123.207.122.156:8080/tdw/alerts/
*
* @return
*/
@Bean
@Order(2)
public FilterRegistrationBean getCasAuthFilterRegistrationBean() {
FilterRegistrationBean registration = new FilterRegistrationBean();
final Filter casAuthFilter = getCasAuthFilter();
registration.setFilter(casAuthFilter);
registration.addUrlPatterns("/*", "*.html");
registration.addInitParameter("casServerLoginUrl", casServerLoginUrl);
registration.addInitParameter("serverName", clienthosturl);
registration.setName(CAS_AUTH_FILTER_NAME);
registration.setEnabled(true);
return registration;
}
@Bean(name = CAS_AUTH_FILTER_NAME)
public Filter getCasAuthFilter() {
return new MyAuthenticationFilter();
}
/**
* Yes Ticket check
* casValidationServerUrlPrefix Use the intranet ip
* casValidationServerUrlPrefix:https://123.207.122.156:8081/cas
* casServerName:https://123.207.122.156:8080/tdw/alerts/
*
* @return
*/
@Bean
@Order(3)
public FilterRegistrationBean getCasValidationFilterRegistrationBean() {
FilterRegistrationBean registration = new FilterRegistrationBean();
final Filter casValidationFilter = getCasValidationFilter();
registration.setFilter(casValidationFilter);
registration.addUrlPatterns("/*", "*.html");
registration.addInitParameter("casServerUrlPrefix", casValidationServerUrlPrefix);
registration.addInitParameter("serverName", clienthosturl);
registration.setName(CAS_FILTER_NAME);
registration.setEnabled(true);
return registration;
}
@Bean(name = CAS_FILTER_NAME)
public Filter getCasValidationFilter() {
return new Cas20ProxyReceivingTicketValidationFilter();
}
/**
* Set up response The default encoding of :UTF-8.
*
* @return
*/
@Bean
@Order(4)
public FilterRegistrationBean getCharacterEncodingFilterRegistrationBean() {
FilterRegistrationBean registration = new FilterRegistrationBean();
registration.setFilter(getCharacterEncodingFilter());
registration.addUrlPatterns("/*", "*.html");
registration.setName(CHARACTER_ENCODING_NAME);
registration.setEnabled(true);
return registration;
}
@Bean(name = CHARACTER_ENCODING_NAME)
public Filter getCharacterEncodingFilter() {
CharacterEncodingFilter characterEncodingFilter = new CharacterEncodingFilter();
characterEncodingFilter.setEncoding("UTF-8");
return characterEncodingFilter;
}
@Bean
public FilterRegistrationBean casHttpServletRequestWrapperFilter(){
FilterRegistrationBean authenticationFilter = new FilterRegistrationBean();
authenticationFilter.setFilter(new HttpServletRequestWrapperFilter());
authenticationFilter.setOrder(6);
List<String> urlPatterns = new ArrayList<>();
urlPatterns.add("/*");
authenticationFilter.setUrlPatterns(urlPatterns);
return authenticationFilter;
}
@Override
public void afterPropertiesSet() throws Exception {
}
}4.filter Class MyAuthenticationFilter It's rewriting cas jar In bag AuthenticationFilter, as a result of CAS The source code cannot authenticate the direct redirection , and ajax Requests cannot be redirected directly , Leading to the front end 302, and 302vue response Interceptors cannot intercept . So I thought of not letting cas Redirect me , Return the status code to me , Tell the front end that authentication failed , Let the front end jump directly cas Server login address .
modify cas Source filter , Copy source code AuthenticationFilter This filter , Rewrite him , In fact, only the redirection code is changed here. Everything else is the same . On MyAuthenticationFilter Code
package com.casclient1.cas.config;
import org.jasig.cas.client.authentication.*;
import org.jasig.cas.client.util.AbstractCasFilter;
import org.jasig.cas.client.util.CommonUtils;
import org.jasig.cas.client.util.ReflectUtils;
import org.jasig.cas.client.validation.Assertion;
import javax.servlet.FilterConfig;
import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
public class MyAuthenticationFilter extends AbstractCasFilter {
private String casServerLoginUrl;
private boolean renew = false;
private boolean gateway = false;
private GatewayResolver gatewayStorage = new DefaultGatewayResolverImpl();
private AuthenticationRedirectStrategy authenticationRedirectStrategy = new DefaultAuthenticationRedirectStrategy();
private UrlPatternMatcherStrategy ignoreUrlPatternMatcherStrategyClass = null;
private static final Map<String, Class<? extends UrlPatternMatcherStrategy>> PATTERN_MATCHER_TYPES = new HashMap();
public MyAuthenticationFilter() {
}
@Override
protected void initInternal(FilterConfig filterConfig) throws ServletException {
if (!this.isIgnoreInitConfiguration()) {
super.initInternal(filterConfig);
this.setCasServerLoginUrl(this.getPropertyFromInitParams(filterConfig, "casServerLoginUrl", (String)null));
this.logger.trace("Loaded CasServerLoginUrl parameter: {}", this.casServerLoginUrl);
this.setRenew(this.parseBoolean(this.getPropertyFromInitParams(filterConfig, "renew", "false")));
this.logger.trace("Loaded renew parameter: {}", this.renew);
this.setGateway(this.parseBoolean(this.getPropertyFromInitParams(filterConfig, "gateway", "false")));
this.logger.trace("Loaded gateway parameter: {}", this.gateway);
String ignorePattern = this.getPropertyFromInitParams(filterConfig, "ignorePattern", (String)null);
this.logger.trace("Loaded ignorePattern parameter: {}", ignorePattern);
String ignoreUrlPatternType = this.getPropertyFromInitParams(filterConfig, "ignoreUrlPatternType", "REGEX");
this.logger.trace("Loaded ignoreUrlPatternType parameter: {}", ignoreUrlPatternType);
if (ignorePattern != null) {
Class<? extends UrlPatternMatcherStrategy> ignoreUrlMatcherClass = (Class)PATTERN_MATCHER_TYPES.get(ignoreUrlPatternType);
if (ignoreUrlMatcherClass != null) {
this.ignoreUrlPatternMatcherStrategyClass = (UrlPatternMatcherStrategy) ReflectUtils.newInstance(ignoreUrlMatcherClass.getName(), new Object[0]);
} else {
try {
this.logger.trace("Assuming {} is a qualified class name...", ignoreUrlPatternType);
this.ignoreUrlPatternMatcherStrategyClass = (UrlPatternMatcherStrategy)ReflectUtils.newInstance(ignoreUrlPatternType, new Object[0]);
} catch (IllegalArgumentException var6) {
this.logger.error("Could not instantiate class [{}]", ignoreUrlPatternType, var6);
}
}
if (this.ignoreUrlPatternMatcherStrategyClass != null) {
this.ignoreUrlPatternMatcherStrategyClass.setPattern(ignorePattern);
}
}
String gatewayStorageClass = this.getPropertyFromInitParams(filterConfig, "gatewayStorageClass", (String)null);
if (gatewayStorageClass != null) {
this.gatewayStorage = (GatewayResolver)ReflectUtils.newInstance(gatewayStorageClass, new Object[0]);
}
String authenticationRedirectStrategyClass = this.getPropertyFromInitParams(filterConfig, "authenticationRedirectStrategyClass", (String)null);
if (authenticationRedirectStrategyClass != null) {
this.authenticationRedirectStrategy = (AuthenticationRedirectStrategy)ReflectUtils.newInstance(authenticationRedirectStrategyClass, new Object[0]);
}
}
}
@Override
public void init() {
super.init();
CommonUtils.assertNotNull(this.casServerLoginUrl, "casServerLoginUrl cannot be null.");
}
@Override
public final void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest)servletRequest;
HttpServletResponse response = (HttpServletResponse)servletResponse;
if (this.isRequestUrlExcluded(request)) {
this.logger.debug("Request is ignored.");
filterChain.doFilter(request, response);
} else {
HttpSession session = request.getSession(false);
Assertion assertion = session != null ? (Assertion)session.getAttribute("_const_cas_assertion_") : null;
if (assertion != null) {
filterChain.doFilter(request, response);
} else {
String serviceUrl = this.constructServiceUrl(request, response);
String ticket = this.retrieveTicketFromRequest(request);
boolean wasGatewayed = this.gateway && this.gatewayStorage.hasGatewayedAlready(request, serviceUrl);
if (!CommonUtils.isNotBlank(ticket) && !wasGatewayed) {
this.logger.debug("no ticket and no assertion found");
String modifiedServiceUrl;
if (this.gateway) {
this.logger.debug("setting gateway attribute in session");
modifiedServiceUrl = this.gatewayStorage.storeGatewayInformation(request, serviceUrl);
} else {
modifiedServiceUrl = serviceUrl;
}
this.logger.debug("Constructed service url: {}", modifiedServiceUrl);
String xRequested =request.getHeader("x-requested-with");
if("XMLHttpRequest".equals(xRequested)){
response.getWriter().write("{\"code\":202, \"msg\":\"no ticket and no assertion found\"}");
}else{
String urlToRedirectTo = CommonUtils.constructRedirectUrl(this.casServerLoginUrl, this.getServiceParameterName(), modifiedServiceUrl, this.renew, this.gateway);
this.logger.debug("redirecting to \"{}\"", urlToRedirectTo);
this.authenticationRedirectStrategy.redirect(request, response, urlToRedirectTo);
}
} else {
filterChain.doFilter(request, response);
}
}
}
}
public final void setRenew(boolean renew) {
this.renew = renew;
}
public final void setGateway(boolean gateway) {
this.gateway = gateway;
}
public final void setCasServerLoginUrl(String casServerLoginUrl) {
this.casServerLoginUrl = casServerLoginUrl;
}
public final void setGatewayStorage(GatewayResolver gatewayStorage) {
this.gatewayStorage = gatewayStorage;
}
private boolean isRequestUrlExcluded(HttpServletRequest request) {
if (this.ignoreUrlPatternMatcherStrategyClass == null) {
return false;
} else {
StringBuffer urlBuffer = request.getRequestURL();
if (request.getQueryString() != null) {
urlBuffer.append("?").append(request.getQueryString());
}
String requestUri = urlBuffer.toString();
return this.ignoreUrlPatternMatcherStrategyClass.matches(requestUri);
}
}
static {
PATTERN_MATCHER_TYPES.put("CONTAINS", ContainsPatternUrlPatternMatcherStrategy.class);
PATTERN_MATCHER_TYPES.put("REGEX", RegexUrlPatternMatcherStrategy.class);
PATTERN_MATCHER_TYPES.put("EXACT", ExactUrlPatternMatcherStrategy.class);
}
}test Controller
package com.casclient1.cas.controller;
import com.casclient1.cas.domain.UserDomain;
import com.casclient1.cas.tools.Result;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.Console;
import java.io.IOException;
@Controller
public class TestController {
/**
* test
* @return
*/
@GetMapping("/test")
@ResponseBody
public Result<UserDomain> login(HttpServletRequest httpServletRequest){
System.out.println("sss");
return new Result<>(new UserDomain(httpServletRequest.getRemoteUser()));
}
@GetMapping("/checkTicket")
public void index(HttpServletResponse response) throws IOException {
// Front page address
response.sendRedirect("http://127.0.0.1:8088/Home");
}
/**
* Cancellation
* @return
*/
@RequestMapping("/logout")
public String logout(){
return "redirect:https://127.0.0.1:8443/cas/logout";
}
}3. front end
<template xmlns="http://www.w3.org/1999/html">
<div >
<header style="height: 60px">
<span> client 2 verification :{
{name}}</span>
<button @click="logout"> Safety exit </button>
</header>
<router-view></router-view>
<!--
<my-vue v-bind:lineID="lineID"></my-vue>-->
</div>
</template>
<style lang="scss">
</style>
<script type="text/ecmascript-6">
export default {
data() {
return {
name:'ss'
}
},
mounted(){
var _this = this;
this.$http.get('/test', {headers: {'x-requested-with': 'XMLHttpRequest'}})
.then(function (response) {
console.log("sss");
if (response.data.code === 202) {
debugger
console.log("sss");
window.location.href = "http://127.0.0.1:1235/checkTicket"
} else if (response.data.code === 200) {
console.log("sss");
_this.name = response.data.data.name
}
console.log(response);
})
.catch(function (error) {
console.log(error);
});
},
methods: {
logout() {
window.location.href = "http://127.0.0.1:1234/logout"
},
}
}
</script>5. effect
Not logged in :

Click client 1 Hyperlinks

Login successful

Click client 2 Hyperlinks , Go straight into , No need to log in .

sign out

summary
There are many on the Internet CAS Single sign on demo, However, there is little detail about the separation of front and rear ends , Fore and aft end separation , There must be cross domain , Lead to CAS Login cannot be redirected, etc , Combined with some ideas and department codes on the Internet , We have made a relatively perfect , But a very basic single sign on System , Of course, single sign on is not just about CAS, also JWT(1. All services are generated by contract token,2. Or generate and judge in a centralized way , All services can recognize this , Or a service can control the whole situation ),OAuth2 wait .
blog.csdn.net/weixin_43483911/article/details/117811270
END
After reading this article, there are gains ? Please forward to share with more people
Focus on 「Java Programming duck 」, promote Java Skill
Focus on Java Programming duck WeChat official account , The background to reply : Yard farm gift bag A copy of the latest technical data can be obtained . cover Java Frame learning 、 Architect learning, etc !
If the article helps , Looking at , Forward! .
Thank you for your support (*^__^*)边栏推荐
- Record the memory leak of viewpager + recyclerview once
- HMS Core音频编辑服务3D音频技术,助力打造沉浸式听觉盛宴
- Boost研究:Boost Log
- Lucene full text search toolkit learning notes summary
- Summer vacation study record
- MCU firmware packaging Script Software
- win10 R包安装报错:没有安装在arch=i386
- 100 important knowledge points that SQL must master: updating and deleting data
- TypeScript ReadonlyArray(只读数组类型) 详细介绍
- Xu Lei expressed three thanks for the most difficult 618 in 19 years
猜你喜欢

国内首批!阿里云云原生数据湖产品通过信通院评测认证

Multiparty Cardinality Testing for Threshold Private Set-2021:解读

启明星辰集团运维安全网关(堡垒机)再次夺得榜首!

The operation and maintenance security gateway (Fortress machine) of Qiming star group once again won the first place!

Who still remembers "classmate Zhang"?

基于视觉的机器人抓取:从物体定位、物体姿态估计到平行抓取器抓取估计

dplyr 中的filter报错:Can‘t transform a data frame with duplicate names

数学(快速幂)

"New digital technology" completed tens of millions of yuan of a + round financing and built an integrated intelligent database cloud management platform

60 个神级 VS Code 插件!!
随机推荐
Object mapping - mapping Mapster
Record the memory leak of viewpager + recyclerview once
"New digital technology" completed tens of millions of yuan of a + round financing and built an integrated intelligent database cloud management platform
The first batch in China! Alibaba cloud native data Lake products have passed the evaluation and certification of the ICT Institute
Alibaba cloud database represented by polardb ranks first in the world
wallys/600VX – 2×2 MIMO 802.11ac Mini PCIe Wi-Fi Module, Dual Band, 2,4GHz / 5GHz QCA 9880
In depth analysis of Apache bookkeeper series: Part 4 - back pressure
EMC-浪涌
Wechat Emoji is written into the judgment, and every Emoji you send may become evidence in court
Webview,ScrollView滑动冲突咋整
100 important knowledge points that SQL must master: join table
It's time for the kotlin coroutine to schedule thread switching to solve the mystery
STM32F407ZGT6使用SDIO方式驱动SD卡
R语言查看版本 R包查看版本
Summer vacation study record
Flutter start from scratch 008 form
Lucene full text search toolkit learning notes summary
Summer vacation study record
对象映射 - Mapping.Mapster
promise async和await的方法与使用