当前位置:网站首页>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 (*^__^*)边栏推荐
- R language de duplication operation unique duplicate filter
- 什么是微信小程序,带你推开小程序的大门
- In depth analysis of Apache bookkeeper series: Part 4 - back pressure
- The operation and maintenance security gateway (Fortress machine) of Qiming star group once again won the first place!
- Database connection pool Druid
- 10 days to learn how to flutter Day10 flutter play animation and packaging
- Line generation (Gauss elimination method, linear basis)
- 基于视觉的机器人抓取:从物体定位、物体姿态估计到平行抓取器抓取估计
- He was the first hero of Shanghai's two major industries, but died silently in regret
- "War" caused by a bottle of water
猜你喜欢

R language view version R package view version

对象映射 - Mapping.Mapster

Win10 R package installation error: not installed in arch=i386

promise async和await的方法与使用

"War" caused by a bottle of water

Wechat Emoji is written into the judgment, and every Emoji you send may become evidence in court

建立自己的网站(13)

科普达人丨漫画图解什么是eRDMA?

暑假学习记录

What is erdma as illustrated by Coptic cartoon?
随机推荐
Webview,ScrollView滑动冲突咋整
100 important knowledge points that SQL must master: grouping data
Use of switch statement in go language learning
If it is not listed again, Kuangshi technology will not be able to endure
PointDistiller:面向高效紧凑3D检测的结构化知识蒸馏
"War" caused by a bottle of water
Evaluation of IP location query interface Ⅲ
重新理解oauth2.0协议进行联合登录
数学(快速幂)
Flutter 从零开始 008 表单
promise async和await的方法与使用
科普達人丨漫畫圖解什麼是eRDMA?
谁还记得「张同学」?
The first batch in China! Alibaba cloud native data Lake products have passed the evaluation and certification of the ICT Institute
Database cascading operation
Xu Lei expressed three thanks for the most difficult 618 in 19 years
【小程序实战系列】小程序框架 页面注册 生命周期 介绍
数据库 事务
Mathematics (fast power)
10 days to learn how to flutter Day10 flutter play animation and packaging