当前位置:网站首页>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 (*^__^*)边栏推荐
- 暑假学习记录
- "War" caused by a bottle of water
- 缓存雪崩和缓存穿透解决方案
- 孔松(信通院)-数字化时代云安全能力建设及趋势
- 据说用了这个,老板连夜把测试开了
- CVPR 2022 | greatly reduce the manual annotation required for zero sample learning. Mapu and Beiyou proposed category semantic embedding rich in visual information
- Compression state DP bit operation
- 一瓶水引发的“战争”
- STM32F407ZGT6使用SDIO方式驱动SD卡
- 来聊聊怎么做硬件兼容性检测,快速迁移到openEuler?
猜你喜欢

Who still remembers "classmate Zhang"?

Limited time appointment | Apache pulsar Chinese developer and user group meeting in June

关于IP定位查询接口的测评Ⅲ

19年来最艰难的618,徐雷表达三个谢意

led背光板的作用是什么呢?

Uncover the whole link communication process of customer service im

Summer vacation study record

wallys/600VX – 2×2 MIMO 802.11ac Mini PCIe Wi-Fi Module, Dual Band, 2,4GHz / 5GHz QCA 9880

60 个神级 VS Code 插件!!

dplyr 中的filter报错:Can‘t transform a data frame with duplicate names
随机推荐
led背光板的作用是什么呢?
STM32F407ZGT6使用SDIO方式驱动SD卡
win10 R包安装报错:没有安装在arch=i386
100 important knowledge points that SQL must master: using table aliases
Xu Lei expressed three thanks for the most difficult 618 in 19 years
R language view version R package view version
Object mapping - mapping Mapster
How to 'gracefully' avoid MySQL login prompt information in scripts
国产数据库的黄金周期要来了吗?
一瓶水引发的“战争”
H3C switch emptying configuration
启明星辰集团运维安全网关(堡垒机)再次夺得榜首!
Alibaba cloud lifeifei: China's cloud database has taken the lead in many mainstream technological innovations abroad
100 important knowledge points that SQL must master: updating and deleting data
10 days to learn how to flutter Day10 flutter play animation and packaging
Alibaba cloud database represented by polardb ranks first in the world
EMC-浪涌
盘点那些具有特色的写作软件
再不上市,旷视科技就熬不住了
以PolarDB为代表的阿里云数据库以跻身全球第一阵营