过滤器配置

客户端会在web.xml配置过滤器,官方给的example中web.xml的内容如下:

<?xml version="1.0" encoding="UTF-8"?><web-app version="2.4" xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd"><!--<context-param><param-name>renew</param-name><param-value>true</param-value></context-param>
--><filter><filter-name>CAS Single Sign Out Filter</filter-name><filter-class>org.jasig.cas.client.session.SingleSignOutFilter</filter-class><init-param><param-name>casServerUrlPrefix</param-name><param-value>https://mmoayyed.unicon.net:8443/cas</param-value></init-param></filter><listener><listener-class>org.jasig.cas.client.session.SingleSignOutHttpSessionListener</listener-class></listener><filter><filter-name>CAS Authentication Filter</filter-name><!--<filter-class>org.jasig.cas.client.authentication.Saml11AuthenticationFilter</filter-class>--><filter-class>org.jasig.cas.client.authentication.AuthenticationFilter</filter-class><init-param><param-name>casServerLoginUrl</param-name><param-value>https://mmoayyed.unicon.net:8443/cas/login</param-value></init-param><init-param><param-name>serverName</param-name><param-value>https://mmoayyed.unicon.net:9443</param-value></init-param></filter><filter><filter-name>CAS Validation Filter</filter-name><!--<filter-class>org.jasig.cas.client.validation.Saml11TicketValidationFilter</filter-class>--><filter-class>org.jasig.cas.client.validation.Cas30ProxyReceivingTicketValidationFilter</filter-class><init-param><param-name>casServerUrlPrefix</param-name><param-value>https://mmoayyed.unicon.net:8443/cas</param-value></init-param><init-param><param-name>serverName</param-name><param-value>https://mmoayyed.unicon.net:9443</param-value></init-param><init-param><param-name>redirectAfterValidation</param-name><param-value>true</param-value></init-param><init-param><param-name>useSession</param-name><param-value>true</param-value></init-param><!--<init-param><param-name>acceptAnyProxy</param-name><param-value>true</param-value></init-param><init-param><param-name>proxyReceptorUrl</param-name><param-value>/sample/proxyUrl</param-value></init-param><init-param><param-name>proxyCallbackUrl</param-name><param-value>https://mmoayyed.unicon.net:9443/sample/proxyUrl</param-value></init-param>--><init-param><param-name>authn_method</param-name><param-value>mfa-duo</param-value></init-param></filter><filter><filter-name>CAS HttpServletRequest Wrapper Filter</filter-name><filter-class>org.jasig.cas.client.util.HttpServletRequestWrapperFilter</filter-class></filter><filter-mapping><filter-name>CAS Single Sign Out Filter</filter-name><url-pattern>/*</url-pattern></filter-mapping><filter-mapping><filter-name>CAS Validation Filter</filter-name><url-pattern>/*</url-pattern></filter-mapping><filter-mapping><filter-name>CAS Authentication Filter</filter-name><url-pattern>/*</url-pattern></filter-mapping><filter-mapping><filter-name>CAS HttpServletRequest Wrapper Filter</filter-name><url-pattern>/*</url-pattern></filter-mapping><welcome-file-list><welcome-file>index.jsp</welcome-file></welcome-file-list>
</web-app>

主要配置了四个过滤器:

  1. CAS Single Sign Out Filter——SingleSignOutFilter
    1. 实现单点登出,放在首个位置;
  2. CAS Validation Filter——Cas30ProxyReceivingTicketValidationFilter
    1. 负责对Ticket的校验
    2. 需要指定服务端地址:casServerUrlPrefix
    3. 需要指定客户端地址:serverName
  3. CAS Authentication Filter——AuthenticationFilter
    1. 负责用户的鉴权
    2. 需要指定服务端登录地址:casServerLoginUrl
    3. 需要指定客户端地址:serverName
  4. CAS HttpServletRequest Wrapper Filter——HttpServletRequestWrapperFilter
    1. 负责包装HttpServletRequest,从而可通过HttpServletRequest的getRemoteUser()方法获取登录用户的登录名

SingleSignOutFilter

简介

实现单点登出功能;

核心代码

private static final SingleSignOutHandler HANDLER = new SingleSignOutHandler();public void init(final FilterConfig filterConfig) throws ServletException {super.init(filterConfig);if (!isIgnoreInitConfiguration()) {// 设置属性setArtifactParameterName(getString(ConfigurationKeys.ARTIFACT_PARAMETER_NAME));setLogoutParameterName(getString(ConfigurationKeys.LOGOUT_PARAMETER_NAME));setFrontLogoutParameterName(getString(ConfigurationKeys.FRONT_LOGOUT_PARAMETER_NAME));setRelayStateParameterName(getString(ConfigurationKeys.RELAY_STATE_PARAMETER_NAME));setCasServerUrlPrefix(getString(ConfigurationKeys.CAS_SERVER_URL_PREFIX));HANDLER.setArtifactParameterOverPost(getBoolean(ConfigurationKeys.ARTIFACT_PARAMETER_OVER_POST));HANDLER.setEagerlyCreateSessions(getBoolean(ConfigurationKeys.EAGERLY_CREATE_SESSIONS));}// handler初始化HANDLER.init();// 设置handler初始化完成标识handlerInitialized.set(true);
}public void doFilter(final ServletRequest servletRequest, final ServletResponse servletResponse,final FilterChain filterChain) throws IOException, ServletException {final HttpServletRequest request = (HttpServletRequest) servletRequest;final HttpServletResponse response = (HttpServletResponse) servletResponse;/*** <p>Workaround for now for the fact that Spring Security will fail since it doesn't call {@link #init(javax.servlet.FilterConfig)}.</p>* <p>Ultimately we need to allow deployers to actually inject their fully-initialized {@link org.jasig.cas.client.session.SingleSignOutHandler}.</p>*/// 校验handler是否初始化完成if (!this.handlerInitialized.getAndSet(true)) {HANDLER.init();}// 根据handler的处理选择是否继续过滤器链if (HANDLER.process(request, response)) {filterChain.doFilter(servletRequest, servletResponse);}
}

首先分析设置属性的操作,设置属性时用到了getString方法,该方法继承自父类AbstractConfigurationFilter,代码如下:

protected final String getString(final ConfigurationKey<String> configurationKey) {return this.configurationStrategy.getString(configurationKey);
}

getString使用了this.configurationStrategy,继续看下该属性的赋值,代码如下:

private static final String CONFIGURATION_STRATEGY_KEY = "configurationStrategy";public void init(FilterConfig filterConfig) throws ServletException {// 从配置中获取configurationStrategy的配置信息final String configurationStrategyName = filterConfig.getServletContext().getInitParameter(CONFIGURATION_STRATEGY_KEY);// 根据configurationStrategy的配置信息获取ConfigurationStrategy实例this.configurationStrategy = ReflectUtils.newInstance(ConfigurationStrategyName.resolveToConfigurationStrategy(configurationStrategyName));// 执行初始化操作this.configurationStrategy.init(filterConfig, getClass());
}// ConfigurationStrategyName.javaDEFAULT(LegacyConfigurationStrategyImpl.class),public static Class<? extends ConfigurationStrategy> resolveToConfigurationStrategy(final String value) {if (CommonUtils.isBlank(value)) {// 若为空,返回默认值LegacyConfigurationStrategyImpl.classreturn DEFAULT.configurationStrategyClass;}for (final ConfigurationStrategyName csn : values()) {if (csn.name().equalsIgnoreCase(value)) {return csn.configurationStrategyClass;}}try {final Class<?> clazz = Class.forName(value);if (ConfigurationStrategy.class.isAssignableFrom(clazz)) {return (Class<? extends ConfigurationStrategy>) clazz;}}   catch (final ClassNotFoundException e) {LOGGER.error("Unable to locate strategy {} by name or class name.  Using default strategy instead.", value, e);}return DEFAULT.configurationStrategyClass;
}

若配置文件中没有配置configurationStrategy,则默认创建LegacyConfigurationStrategyImpl实例,该类型是WebXmlConfigurationStrategyImplJndiConfigurationStrategyImpl的包装,优先使用WebXmlConfigurationStrategyImpl,核心代码如下:

private final WebXmlConfigurationStrategyImpl webXmlConfigurationStrategy = new WebXmlConfigurationStrategyImpl();
private final JndiConfigurationStrategyImpl jndiConfigurationStrategy = new JndiConfigurationStrategyImpl();public void init(FilterConfig filterConfig, Class<? extends Filter> filterClazz) {this.webXmlConfigurationStrategy.init(filterConfig, filterClazz);this.jndiConfigurationStrategy.init(filterConfig, filterClazz);
}protected String get(final ConfigurationKey key) {// 优先使用WebXmlConfigurationStrategyImplfinal String value1 = this.webXmlConfigurationStrategy.get(key);if (CommonUtils.isNotBlank(value1)) {return value1;}return this.jndiConfigurationStrategy.get(key);
}

接着分析SingleSignOutHandler的实现,其核心代码如下:

public boolean process(final HttpServletRequest request, final HttpServletResponse response) {if (isTokenRequest(request)) {// 若是携带token的请求logger.trace("Received a token request");// 记录sessionrecordSession(request);// 返回true,继续执行过滤器链return true;} else if (isBackChannelLogoutRequest(request)) {// 若是后置通道登出请求logger.trace("Received a back channel logout request");// 销毁sessiondestroySession(request);// 返回false,终止执行过滤器链return false;} else if (isFrontChannelLogoutRequest(request)) {// 若是前置通道登出请求logger.trace("Received a front channel logout request");// 销毁sessiondestroySession(request);// redirection url to the CAS serverfinal String redirectionUrl = computeRedirectionToServer(request);if (redirectionUrl != null) {// 重定向到CAS ServerCommonUtils.sendRedirect(response, redirectionUrl);}// 返回false,终止执行过滤器链return false;} else {logger.trace("Ignoring URI for logout: {}", request.getRequestURI());// 默认返回true,继续执行过滤器链return true;}
}private boolean isTokenRequest(final HttpServletRequest request) {return CommonUtils.isNotBlank(CommonUtils.safeGetParameter(request, this.artifactParameterName,this.safeParameters));
}private boolean isBackChannelLogoutRequest(final HttpServletRequest request) {return "POST".equals(request.getMethod())&& !isMultipartRequest(request)&& CommonUtils.isNotBlank(CommonUtils.safeGetParameter(request, this.logoutParameterName,this.safeParameters));
}private boolean isFrontChannelLogoutRequest(final HttpServletRequest request) {return "GET".equals(request.getMethod()) && CommonUtils.isNotBlank(this.casServerUrlPrefix)&& CommonUtils.isNotBlank(CommonUtils.safeGetParameter(request, this.frontLogoutParameterName));
}private void recordSession(final HttpServletRequest request) {final HttpSession session = request.getSession(this.eagerlyCreateSessions);if (session == null) {logger.debug("No session currently exists (and none created).  Cannot record session information for single sign out.");return;}final String token = CommonUtils.safeGetParameter(request, this.artifactParameterName, this.safeParameters);logger.debug("Recording session for token {}", token);try {// 移除已缓存的session信息this.sessionMappingStorage.removeBySessionById(session.getId());} catch (final Exception e) {// ignore if the session is already marked as invalid.  Nothing we can do!}// 缓存当前token和sessionsessionMappingStorage.addSessionById(token, session);
}private void destroySession(final HttpServletRequest request) {final String logoutMessage;// front channel logout -> the message needs to be base64 decoded + decompressedif (isFrontChannelLogoutRequest(request)) {logoutMessage = uncompressLogoutMessage(CommonUtils.safeGetParameter(request,this.frontLogoutParameterName));} else {logoutMessage = CommonUtils.safeGetParameter(request, this.logoutParameterName, this.safeParameters);}logger.trace("Logout request:\n{}", logoutMessage);final String token = XmlUtils.getTextForElement(logoutMessage, "SessionIndex");if (CommonUtils.isNotBlank(token)) {final HttpSession session = this.sessionMappingStorage.removeSessionByMappingId(token);if (session != null) {final String sessionID = session.getId();logger.debug("Invalidating session [{}] for token [{}]", sessionID, token);try {// 失效sessionsession.invalidate();} catch (final IllegalStateException e) {logger.debug("Error invalidating session.", e);}// 登出this.logoutStrategy.logout(request);}}
}

Cas30ProxyReceivingTicketValidationFilter

简介

负责对Ticket的校验,需要指定服务端地址(casServerUrlPrefix)和客户端地址(serverName);

核心代码

public Cas30ProxyReceivingTicketValidationFilter() {// 支持协议为CAS3super(Protocol.CAS3);// ST校验器使用Cas30ServiceTicketValidatorthis.defaultServiceTicketValidatorClass = Cas30ServiceTicketValidator.class;// PT校验器使用Cas30ProxyTicketValidatorthis.defaultProxyTicketValidatorClass = Cas30ProxyTicketValidator.class;
}

Cas30ProxyReceivingTicketValidationFilter继承自Cas20ProxyReceivingTicketValidationFilter,重写了this.protocolthis.defaultServiceTicketValidatorClassthis.defaultProxyTicketValidatorClass的实现,其它处理都一样,接着分析Cas20ProxyReceivingTicketValidationFilter
Cas20ProxyReceivingTicketValidationFilterdoFilter方法继承自父类AbstractTicketValidationFilterAbstractTicketValidationFilter实现了doFilter方法的算法模板,并提供算法细节preFilteronSuccessfulValidationonFailedValidation可供子类重写添加额外处理逻辑,核心代码如下:

public final void doFilter(final ServletRequest servletRequest, final ServletResponse servletResponse,final FilterChain filterChain) throws IOException, ServletException {// 过滤前预处理if (!preFilter(servletRequest, servletResponse, filterChain)) {return;}final HttpServletRequest request = (HttpServletRequest) servletRequest;final HttpServletResponse response = (HttpServletResponse) servletResponse;// 从请求中获取Ticket信息final String ticket = retrieveTicketFromRequest(request);// 是否存在Ticket信息if (CommonUtils.isNotBlank(ticket)) {logger.debug("Attempting to validate ticket: {}", ticket);try {// 存在Ticket信息就需要校验final Assertion assertion = this.ticketValidator.validate(ticket,constructServiceUrl(request, response));logger.debug("Successfully authenticated user: {}", assertion.getPrincipal().getName());// 未抛出异常,则校验成功// 将校验结果放入request请求中,方便下次获取request.setAttribute(CONST_CAS_ASSERTION, assertion);if (this.useSession) {// 使用session情况下,将校验结果方法session属性中request.getSession().setAttribute(CONST_CAS_ASSERTION, assertion);}// 校验成功时处理onSuccessfulValidation(request, response, assertion);if (this.redirectAfterValidation) {// 默认为true,校验后需要重定向logger.debug("Redirecting after successful ticket validation.");response.sendRedirect(constructServiceUrl(request, response));return;}} catch (final TicketValidationException e) {logger.debug(e.getMessage(), e);// 校验失败时处理onFailedValidation(request, response);if (this.exceptionOnValidationFailure) {throw new ServletException(e);}// 返回HttpServletResponse.SC_FORBIDDEN响应response.sendError(HttpServletResponse.SC_FORBIDDEN, e.getMessage());return;}}// 执行过滤器链filterChain.doFilter(request, response);
}protected boolean preFilter(final ServletRequest servletRequest, final ServletResponse servletResponse,final FilterChain filterChain) throws IOException, ServletException {return true;
}protected void onSuccessfulValidation(final HttpServletRequest request, final HttpServletResponse response,final Assertion assertion) {// nothing to do here.
}protected void onFailedValidation(final HttpServletRequest request, final HttpServletResponse response) {// nothing to do here.
}protected String retrieveTicketFromRequest(final HttpServletRequest request) {// 从请求中获取"ticket"信息return CommonUtils.safeGetParameter(request, this.protocol.getArtifactParameterName());
}

对于this.redirectAfterValidation属性需要说明下,该值决定了Ticket校验成功后是否需要重定向:

  1. 如果进行重定向,那么新请求就不会携带Ticket信息,新请求也就不需要再进行Ticket校验处理;但由于AuthenticationFilter是从Session中获取鉴权结果,所以要进行重定向,就必须要支持使用Session,即this.useSession为true;
  2. 如果不进行重定向,那么原请求还会携带Ticket信息,AuthenticationFilter获取到Ticket信息就会放行;

this.redirectAfterValidation属性赋值的相关代码如下:

private boolean redirectAfterValidation = true;protected void initInternal(final FilterConfig filterConfig) throws ServletException {setExceptionOnValidationFailure(getBoolean(ConfigurationKeys.EXCEPTION_ON_VALIDATION_FAILURE));setRedirectAfterValidation(getBoolean(ConfigurationKeys.REDIRECT_AFTER_VALIDATION));setUseSession(getBoolean(ConfigurationKeys.USE_SESSION));if (!this.useSession && this.redirectAfterValidation) {// 如果不使用Session,那么就不支持Ticket校验后重定向到客户端logger.warn("redirectAfterValidation parameter may not be true when useSession parameter is false. Resetting it to false in order to prevent infinite redirects.");setRedirectAfterValidation(false);}setTicketValidator(getTicketValidator(filterConfig));super.initInternal(filterConfig);
}

Cas20ProxyReceivingTicketValidationFilter重写了preFilter,主要针对代理模式下的请求做预处理,代码如下:

protected final boolean preFilter(final ServletRequest servletRequest, final ServletResponse servletResponse,final FilterChain filterChain) throws IOException, ServletException {final HttpServletRequest request = (HttpServletRequest) servletRequest;final HttpServletResponse response = (HttpServletResponse) servletResponse;final String requestUri = request.getRequestURI();// 是否是代理请求if (CommonUtils.isEmpty(this.proxyReceptorUrl) || !requestUri.endsWith(this.proxyReceptorUrl)) {return true;}try {CommonUtils.readAndRespondToProxyReceptorRequest(request, response, this.proxyGrantingTicketStorage);} catch (final RuntimeException e) {logger.error(e.getMessage(), e);throw e;}return false;
}

AbstractTicketValidationFilter.doFilter中使用了this.ticketValidator来校验Ticket信息,Cas30ProxyReceivingTicketValidationFilter中默认使用的是Cas30ServiceTicketValidator,其validate方法继承自父类AbstractUrlBasedTicketValidatorAbstractUrlBasedTicketValidator实现了validate方法的算法模板,提供算法细节retrieveResponseFromServerparseResponseFromServer由子类实现,代码如下:

public final Assertion validate(final String ticket, final String service) throws TicketValidationException {// 构建校验请求URLfinal String validationUrl = constructValidationUrl(ticket, service);logger.debug("Constructing validation url: {}", validationUrl);try {// 发送校验请求并获取服务端响应logger.debug("Retrieving response from server.");final String serverResponse = retrieveResponseFromServer(new URL(validationUrl), ticket);// 返回结果为空则校验失败if (serverResponse == null) {throw new TicketValidationException("The CAS server returned no response.");}logger.debug("Server response: {}", serverResponse);// 解析服务端响应return parseResponseFromServer(serverResponse);} catch (final MalformedURLException e) {throw new TicketValidationException(e);}
}protected abstract String retrieveResponseFromServer(URL validationUrl, String ticket);protected abstract Assertion parseResponseFromServer(final String response) throws TicketValidationException;protected final String constructValidationUrl(final String ticket, final String serviceUrl) {final Map<String, String> urlParameters = new HashMap<String, String>();logger.debug("Placing URL parameters in map.");// 放入Ticket信息urlParameters.put("ticket", ticket);// 放入Service信息urlParameters.put("service", serviceUrl);// 如果包含renewif (this.renew) {urlParameters.put("renew", "true");}logger.debug("Calling template URL attribute map.");// 填充其他属性populateUrlAttributeMap(urlParameters);logger.debug("Loading custom parameters from configuration.");if (this.customParameters != null) {urlParameters.putAll(this.customParameters);}final String suffix = getUrlSuffix();final StringBuilder buffer = new StringBuilder(urlParameters.size() * 10 + this.casServerUrlPrefix.length()+ suffix.length() + 1);int i = 0;// 构造URLbuffer.append(this.casServerUrlPrefix);if (!this.casServerUrlPrefix.endsWith("/")) {buffer.append("/");}buffer.append(suffix);for (Map.Entry<String, String> entry : urlParameters.entrySet()) {final String key = entry.getKey();final String value = entry.getValue();if (value != null) {buffer.append(i++ == 0 ? "?" : "&");buffer.append(key);buffer.append("=");final String encodedValue = encodeUrl(value);buffer.append(encodedValue);}}return buffer.toString();
}

AbstractCasProtocolUrlBasedTicketValidator实现了算法细节的retrieveResponseFromServer的算法模板,代码如下:

protected final String retrieveResponseFromServer(final URL validationUrl, final String ticket) {// 借助CommonUtils实现return CommonUtils.getResponseFromServer(validationUrl, getURLConnectionFactory(), getEncoding());
}// CommonUtils.java
public static String getResponseFromServer(final URL constructedUrl, final HttpURLConnectionFactory factory,final String encoding) {HttpURLConnection conn = null;InputStreamReader in = null;try {conn = factory.buildHttpURLConnection(constructedUrl.openConnection());if (CommonUtils.isEmpty(encoding)) {in = new InputStreamReader(conn.getInputStream());} else {in = new InputStreamReader(conn.getInputStream(), encoding);}// 获取响应final StringBuilder builder = new StringBuilder(255);int byteRead;while ((byteRead = in.read()) != -1) {builder.append((char) byteRead);}// 返回响应return builder.toString();} catch (final Exception e) {LOGGER.error(e.getMessage(), e);throw new RuntimeException(e);} finally {closeQuietly(in);if (conn != null) {conn.disconnect();}}
}

Cas20ServiceTicketValidator实现了算法细节parseResponseFromServer的算法模板,并提供算法细节customParseResponse供子类重写添加额外处理逻辑,代码如下:

protected final Assertion parseResponseFromServer(final String response) throws TicketValidationException {final String error = XmlUtils.getTextForElement(response, "authenticationFailure");if (CommonUtils.isNotBlank(error)) {// 存在错误信息throw new TicketValidationException(error);}final String principal = XmlUtils.getTextForElement(response, "user");final String proxyGrantingTicketIou = XmlUtils.getTextForElement(response, "proxyGrantingTicket");// 获取PGT信息final String proxyGrantingTicket;if (CommonUtils.isBlank(proxyGrantingTicketIou) || this.proxyGrantingTicketStorage == null) {proxyGrantingTicket = null;} else {proxyGrantingTicket = this.proxyGrantingTicketStorage.retrieve(proxyGrantingTicketIou);}// 校验principal信息if (CommonUtils.isEmpty(principal)) {throw new TicketValidationException("No principal was found in the response from the CAS server.");}// 封装Assertion信息final Assertion assertion;final Map<String, Object> attributes = extractCustomAttributes(response);if (CommonUtils.isNotBlank(proxyGrantingTicket)) {final AttributePrincipal attributePrincipal = new AttributePrincipalImpl(principal, attributes,proxyGrantingTicket, this.proxyRetriever);assertion = new AssertionImpl(attributePrincipal);} else {assertion = new AssertionImpl(new AttributePrincipalImpl(principal, attributes));}// 支持子类定制化解析Assertion信息customParseResponse(response, assertion);return assertion;
}protected Map<String, Object> extractCustomAttributes(final String xml) {final SAXParserFactory spf = SAXParserFactory.newInstance();spf.setNamespaceAware(true);spf.setValidating(false);try {final SAXParser saxParser = spf.newSAXParser();final XMLReader xmlReader = saxParser.getXMLReader();final CustomAttributeHandler handler = new CustomAttributeHandler();xmlReader.setContentHandler(handler);xmlReader.parse(new InputSource(new StringReader(xml)));return handler.getAttributes();} catch (final Exception e) {logger.error(e.getMessage(), e);return Collections.emptyMap();}
}protected void customParseResponse(final String response, final Assertion assertion)throws TicketValidationException {// nothing to do
}

AuthenticationFilter

简介

负责用户的鉴权,需要指定服务端登录地址(casServerLoginUrl)和客户端地址(serverName);

核心代码

public final void doFilter(final ServletRequest servletRequest, final ServletResponse servletResponse,final FilterChain filterChain) throws IOException, ServletException {final HttpServletRequest request = (HttpServletRequest) servletRequest;final HttpServletResponse response = (HttpServletResponse) servletResponse;if (isRequestUrlExcluded(request)) {logger.debug("Request is ignored.");// 若排除该请求,则直接执行过滤器链filterChain.doFilter(request, response);return;}// 尝试获取Assertion信息final HttpSession session = request.getSession(false);final Assertion assertion = session != null ? (Assertion) session.getAttribute(CONST_CAS_ASSERTION) : null;if (assertion != null) {// 若Assertion存在,则无需鉴权,直接执行过滤器链filterChain.doFilter(request, response);return;}// 构造本客户端URLfinal String serviceUrl = constructServiceUrl(request, response);// 从request请求中获取Ticket信息final String ticket = retrieveTicketFromRequest(request);final boolean wasGatewayed = this.gateway && this.gatewayStorage.hasGatewayedAlready(request, serviceUrl);if (CommonUtils.isNotBlank(ticket) || wasGatewayed) {// 若存在Ticket信息则无需鉴权filterChain.doFilter(request, response);return;}final String modifiedServiceUrl;logger.debug("no ticket and no assertion found");if (this.gateway) {logger.debug("setting gateway attribute in session");modifiedServiceUrl = this.gatewayStorage.storeGatewayInformation(request, serviceUrl);} else {modifiedServiceUrl = serviceUrl;}logger.debug("Constructed service url: {}", modifiedServiceUrl);final String urlToRedirectTo = CommonUtils.constructRedirectUrl(this.casServerLoginUrl,getProtocol().getServiceParameterName(), modifiedServiceUrl, this.renew, this.gateway);// 重定向到服务端进行登录鉴权logger.debug("redirecting to \"{}\"", urlToRedirectTo);this.authenticationRedirectStrategy.redirect(request, response, urlToRedirectTo);
}

HttpServletRequestWrapperFilter

简介

负责包装HttpServletRequest,从而可通过HttpServletRequest的getRemoteUser()方法获取登录用户的登录名;

核心代码

public void doFilter(final ServletRequest servletRequest, final ServletResponse servletResponse,final FilterChain filterChain) throws IOException, ServletException {// 从request请求或者session中获取Principal信息final AttributePrincipal principal = retrievePrincipalFromSessionOrRequest(servletRequest);// 包装ServletRequest,添加Principal信息filterChain.doFilter(new CasHttpServletRequestWrapper((HttpServletRequest) servletRequest, principal),servletResponse);
}/*** 内部类* 继承自HttpServletRequestWrapper,封装了Principal信息*/
final class CasHttpServletRequestWrapper extends HttpServletRequestWrapper {private final AttributePrincipal principal;CasHttpServletRequestWrapper(final HttpServletRequest request, final AttributePrincipal principal) {super(request);this.principal = principal;}public Principal getUserPrincipal() {return this.principal;}public String getRemoteUser() {return principal != null ? this.principal.getName() : null;}public boolean isUserInRole(final String role) {if (CommonUtils.isBlank(role)) {logger.debug("No valid role provided.  Returning false.");return false;}if (this.principal == null) {logger.debug("No Principal in Request.  Returning false.");return false;}if (CommonUtils.isBlank(roleAttribute)) {logger.debug("No Role Attribute Configured. Returning false.");return false;}final Object value = this.principal.getAttributes().get(roleAttribute);if (value instanceof Collection<?>) {for (final Object o : (Collection<?>) value) {if (rolesEqual(role, o)) {logger.debug("User [{}] is in role [{}]: true", getRemoteUser(), role);return true;}}}final boolean isMember = rolesEqual(role, value);logger.debug("User [{}] is in role [{}]: {}", getRemoteUser(), role, isMember);return isMember;}/*** Determines whether the given role is equal to the candidate* role attribute taking into account case sensitivity.** @param given  Role under consideration.* @param candidate Role that the current user possesses.** @return True if roles are equal, false otherwise.*/private boolean rolesEqual(final String given, final Object candidate) {return ignoreCase ? given.equalsIgnoreCase(candidate.toString()) : given.equals(candidate);}
}
查看全文
如若内容造成侵权/违法违规/事实不符,请联系编程学习网邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!

相关文章

  1. 2022-2000-1978:世纪前后22年

    最近看到一句话&#xff0c;莫名有点触动&#xff1a;“现在到2000年是22年&#xff0c;2000年往前的22年&#xff0c;是1978年”。 如果没算错的话&#xff0c;以2000年1月1日零点为中轴&#xff0c;和现在&#xff08;2022-01-29&#xff09;对称的世纪那一端是1977-12-02 。…...

    2024/4/7 19:13:51
  2. JAVA练习64-序列化二叉树

    请实现两个函数&#xff0c;分别用来序列化和反序列化二叉树。 你需要设计一个算法来实现二叉树的序列化与反序列化。这里不限定你的序列 / 反序列化算法执行逻辑&#xff0c;你只需要保证一个二叉树可以被序列化为一个字符串并且将这个字符串反序列化为原始的树结构。 提示&…...

    2024/4/7 19:13:50
  3. 用贪吃蛇小游戏表白

    在线体验地址&#xff08;电脑键盘控制&#xff09;&#xff1a; 目录如何使用效果及修改完整源码如何使用 文章末尾是该游戏的完整代码&#xff08;基于htmlcssjs&#xff09;&#xff0c;没学过前端或者没有编辑器的朋友不要着急&#xff0c;只要有电脑就可以完整运行此项目…...

    2024/4/13 21:28:25
  4. STM32学习笔记(3)掌握GPIO操作—输入模式(上拉/下拉)

    目录1、输入模式(上拉/下拉)详细说明2、输入模式实现按键控制1、如何判断按键变化&#xff1f;2、按键监测函数1、输入模式(上拉/下拉)详细说明 在输入模式时&#xff0c;施密特触发器打开&#xff0c;输出被禁止。可通过输入数据寄存器 GPIOx_IDR 读取 I/O 状态。输入模式可以…...

    2024/4/18 3:14:02
  5. CentOS8图形界面安装

    百度安全验证https://baijiahao.baidu.com/s?id1667360460947604107&wfrspider&forpc...

    2024/4/15 8:16:28
  6. 快速开发一个h5游戏

    主要就是三个步骤&#xff1a; 选择一个引擎&#xff1a;pixi&#xff0c;实际上就一个js库搭建一个简易的本地服务器&#xff0c;只是为了能够以http形式访问&#xff0c;越简单越好 参考文章&#xff1a;快速搭建一个本地服务器编写一个demo <!doctype html> <htm…...

    2024/4/20 5:16:54
  7. 新域名和老域名SEO优化区别

    用以前的SEO经验看&#xff0c;老域名在SEO优化时具备较强的优势&#xff0c;以前买老域名做站的是主流&#xff0c;就算是现在依然很多人也是如此&#xff0c;对于现在SEO优化来说其实是有点可笑了&#xff0c;但是不能否认老域名在当前SEO优化中还是有一点优势&#xff0c;但…...

    2024/4/13 21:28:20
  8. 解决Python中ZipFile解压文件名中文乱码的问题

    解决Python中ZipFile解压文件名中文乱码的问题问题复现原因分析解决办法问题复现 压缩包目录结构 里面有中文.zip ├── 中文文件.txt └── 中文文件夹└── 中文文件.txt解压代码 from zipfile import ZipFilewith ZipFile(r./里面有中文.zip) as zfp:zfp.extractall(r…...

    2024/4/13 21:28:15
  9. Leetcode数据结构入门第四天(数组)

    Leetcode数据结构入门第四天&#xff08;数组&#xff09;566. 重塑矩阵题目描述示例1&#xff1a;示例2&#xff1a;思路一知识点补充&#xff1a;C 动态二维数组(二维vector&#xff09;参考代码思路二(数组映射方法)参考代码118. 杨辉三角题目描述样例思路知识点参考代码566…...

    2024/4/15 13:22:04
  10. 构建NFS集群文件共享

    Master 1、yum install -y nfs-utils rpcbind 2、cd /usr/local 3、mkdir data 4、cd data 5、mkdir www-data 6、cd www-data 7、vim /etc/exports #构建挂载点 /usr/local/data/www-data 192.168.152.16/24(rw,sync) 8、systemctl start nfs.service #启动nfs服务 9、sy…...

    2024/4/18 14:57:36
  11. 【SLF4J+log4j2】日志输出教程

    目录1. 需要引入的jar包2. 下载log4j2的jar包3. 下载slf4j的jar包4. 例子4.1 添加jar包关联4.2 准备log4j2的配置文件4.3 加载配置文件4.4 写出log4.5 运行java程序后&#xff0c;看log。log4j2是一个日志框架&#xff0c;slf4j是日志框架接口。log4j2和slf4j搭配使用&#xff…...

    2024/4/19 12:10:37
  12. 差分C++差分函数

    原文来自我的博客&#xff1a;www.dorkyfox.com&#xff0c;转载引用请注明出处&#xff01;&#xff01;&#xff01; 差分是前缀和的逆运算。如果将前缀和看作数列an的前n项和Sn&#xff0c;那么差分就是通过Sn求an。 原数组&#xff1a;a[1]、a[2]、a[3]、a[4]、a[5] 差分…...

    2024/4/13 21:29:26
  13. 【苹果推相册软件】imessage群发arrangesAllSubviews安装

    推荐内容IMESSGAE相关 作者推荐内容参考此文档来操作 *** 点击即可查看作者要求内容信息作者推荐内容1.参考此文档来操作 *** 点击即可查看作者要求内容信息作者推荐内容2.参考此文档来操作 *** 点击即可查看作者要求内容信息作者推荐内容3.参考此文档来操作 *** 点击即可查看…...

    2024/4/17 23:15:16
  14. docker 发布.net 5 webapi

    右键WebApi添加&#xff0c;选择Docker支持 系统选择你需要部署的系统&#xff0c;添加成功后会出现Dockerfile这个文件 把文件里面的内容替换成: #基于 microsoft/dotnet:5.0.0-core 来构建我们的镜像 FROM mcr.microsoft.com/dotnet/sdk:5.0#创建项目在docker容器内的工作目…...

    2024/4/5 3:31:16
  15. 中国自行车十大名牌辐轮王土拨鼠全球10万元以上的自行车排行榜

    除了健康&#xff0c;什么都是浮云!没了健康&#xff0c;功名利禄都是浮云;没了健康&#xff0c;半生奔波都是徒劳;没了健康&#xff0c;再多钱财都是虚无。生命是极其宝贵的&#xff0c;生命对于人只有一次&#xff0c;人生没有回程票。互联网日新月异&#xff0c;工作生活节奏…...

    2024/4/13 21:29:26
  16. 【imessage苹果家庭推】最新版软件安装登录设备上的iMessages

    推荐内容IMESSGAE相关 作者推荐内容参考此文档来操作 *** 点击即可查看作者要求内容信息作者推荐内容1.参考此文档来操作 *** 点击即可查看作者要求内容信息作者推荐内容2.参考此文档来操作 *** 点击即可查看作者要求内容信息作者推荐内容3.参考此文档来操作 *** 点击即可查看…...

    2024/4/13 21:29:06
  17. 整人VBS\BAT代码 ② 整蛊系列→可参考

    大家好&#xff0c;我是MouBai00001&#xff0c;刚入站不久的孟新。当你在现实生活中被整&#xff0c;你会有怎样的想法呢&#xff1f; 当你在和朋友在一个Wifi里打电脑游戏时&#xff0c;被你的朋友坑&#xff0c;下面就教大家如何以牙还牙&#xff08;好像营销号&#xff09;…...

    2024/4/13 21:29:21
  18. 无线通信零基础学习记录(2)——GSM空中接口物理层的设计

    无线通信零基础学习记录&#xff08;2&#xff09;——GSM空中接口物理层的设计 本章解释清楚了之前未搞懂的名词&#xff0c;如时隙等&#xff0c;以及各种信道类型&#xff0c;在此一并总结。 TDMA空中接口技术 时分多址&#xff08;TDMA&#xff0c;Time Division Mutipl…...

    2024/4/20 5:20:44
  19. 使用rsync同步时出现 (in rsync_opt)) failed: Permission denied (13)

    检查了服务器的同步的目录权限都没有问题&#xff0c;网上找了说是开启了SELinux 的enforce模式&#xff0c;于事 [roottest01 etc]# getenforce Enforcing 果然是enforce模式&#xff0c;然后 [roottest01 etc]# setenforce 0 关闭enforce模式 [roottest01 etc]# getenforce…...

    2024/4/7 19:13:40
  20. 多态及引用数据类型转换

    多态&#xff1a;多种形态 生活中的多态&#xff1a;同一个操作 因为环境不同 产生不同的效果 代码中的多态&#xff1a;同一个方法&#xff0c;因为实际参数或者返回值的不同&#xff0c;产生不同的效果 多态是面向对象三大特征之一&#xff0c;在实际开发中&#xff0c;多…...

    2024/4/13 21:29:01

最新文章

  1. 天星金融普及银行卡防盗刷知识,助力消费者安全用卡

    移动互联网的迅猛发展推动了手机银行等业务的广泛应用&#xff0c;然而&#xff0c;一些不法分子利用伪造银行卡、窃取持卡人身份信息等手段进行盗刷&#xff0c;严重侵犯了消费者的信息安全和财产安全&#xff0c;对金融市场的稳定和安全造成了威胁。为此&#xff0c;天星金融…...

    2024/4/27 21:54:36
  2. 梯度消失和梯度爆炸的一些处理方法

    在这里是记录一下梯度消失或梯度爆炸的一些处理技巧。全当学习总结了如有错误还请留言&#xff0c;在此感激不尽。 权重和梯度的更新公式如下&#xff1a; w w − η ⋅ ∇ w w w - \eta \cdot \nabla w ww−η⋅∇w 个人通俗的理解梯度消失就是网络模型在反向求导的时候出…...

    2024/3/20 10:50:27
  3. 关于ansible的模块 ③

    转载说明&#xff1a;如果您喜欢这篇文章并打算转载它&#xff0c;请私信作者取得授权。感谢您喜爱本文&#xff0c;请文明转载&#xff0c;谢谢。 接《关于Ansible的模块①》和《关于Ansible的模块②》&#xff0c;继续学习ansible的user模块。 user模块可以增、删、改linux远…...

    2024/4/18 10:52:09
  4. 【JavaScript 漫游】【049】ES6 规范中对象的扩展

    文章简介 本篇文章为【JavaScript 漫游】专栏的第 049 篇文章&#xff0c;对 ES6 规范中对象的扩展知识点进行了记录。具体包括&#xff1a; 属性的简洁表示法属性名表达式方法的 name 属性属性的可枚举性和遍历super 关键字对象的扩展运算符链判断运算符Null 判断运算符新增…...

    2024/4/23 21:45:44
  5. CentOS 7查看磁盘空间

    CentOS如何查看硬盘大小&#xff1f; CentOS是一种基于Linux的操作系统&#xff0c;主要用于服务器端应用。在服务器管理中&#xff0c;硬盘大小是一个非常重要的指标&#xff0c;查看硬盘大小可以帮助系统管理员有效地管理硬盘空间和避免硬盘满了的情况。 方法一&#xff1a…...

    2024/4/24 14:59:47
  6. 【外汇早评】美通胀数据走低,美元调整

    原标题:【外汇早评】美通胀数据走低,美元调整昨日美国方面公布了新一期的核心PCE物价指数数据,同比增长1.6%,低于前值和预期值的1.7%,距离美联储的通胀目标2%继续走低,通胀压力较低,且此前美国一季度GDP初值中的消费部分下滑明显,因此市场对美联储后续更可能降息的政策…...

    2024/4/26 18:09:39
  7. 【原油贵金属周评】原油多头拥挤,价格调整

    原标题:【原油贵金属周评】原油多头拥挤,价格调整本周国际劳动节,我们喜迎四天假期,但是整个金融市场确实流动性充沛,大事频发,各个商品波动剧烈。美国方面,在本周四凌晨公布5月份的利率决议和新闻发布会,维持联邦基金利率在2.25%-2.50%不变,符合市场预期。同时美联储…...

    2024/4/26 20:12:18
  8. 【外汇周评】靓丽非农不及疲软通胀影响

    原标题:【外汇周评】靓丽非农不及疲软通胀影响在刚结束的周五,美国方面公布了新一期的非农就业数据,大幅好于前值和预期,新增就业重新回到20万以上。具体数据: 美国4月非农就业人口变动 26.3万人,预期 19万人,前值 19.6万人。 美国4月失业率 3.6%,预期 3.8%,前值 3…...

    2024/4/26 23:05:52
  9. 【原油贵金属早评】库存继续增加,油价收跌

    原标题:【原油贵金属早评】库存继续增加,油价收跌周三清晨公布美国当周API原油库存数据,上周原油库存增加281万桶至4.692亿桶,增幅超过预期的74.4万桶。且有消息人士称,沙特阿美据悉将于6月向亚洲炼油厂额外出售更多原油,印度炼油商预计将每日获得至多20万桶的额外原油供…...

    2024/4/27 4:00:35
  10. 【外汇早评】日本央行会议纪要不改日元强势

    原标题:【外汇早评】日本央行会议纪要不改日元强势近两日日元大幅走强与近期市场风险情绪上升,避险资金回流日元有关,也与前一段时间的美日贸易谈判给日本缓冲期,日本方面对汇率问题也避免继续贬值有关。虽然今日早间日本央行公布的利率会议纪要仍然是支持宽松政策,但这符…...

    2024/4/27 17:58:04
  11. 【原油贵金属早评】欧佩克稳定市场,填补伊朗问题的影响

    原标题:【原油贵金属早评】欧佩克稳定市场,填补伊朗问题的影响近日伊朗局势升温,导致市场担忧影响原油供给,油价试图反弹。此时OPEC表态稳定市场。据消息人士透露,沙特6月石油出口料将低于700万桶/日,沙特已经收到石油消费国提出的6月份扩大出口的“适度要求”,沙特将满…...

    2024/4/27 14:22:49
  12. 【外汇早评】美欲与伊朗重谈协议

    原标题:【外汇早评】美欲与伊朗重谈协议美国对伊朗的制裁遭到伊朗的抗议,昨日伊朗方面提出将部分退出伊核协议。而此行为又遭到欧洲方面对伊朗的谴责和警告,伊朗外长昨日回应称,欧洲国家履行它们的义务,伊核协议就能保证存续。据传闻伊朗的导弹已经对准了以色列和美国的航…...

    2024/4/26 21:56:58
  13. 【原油贵金属早评】波动率飙升,市场情绪动荡

    原标题:【原油贵金属早评】波动率飙升,市场情绪动荡因中美贸易谈判不安情绪影响,金融市场各资产品种出现明显的波动。随着美国与中方开启第十一轮谈判之际,美国按照既定计划向中国2000亿商品征收25%的关税,市场情绪有所平复,已经开始接受这一事实。虽然波动率-恐慌指数VI…...

    2024/4/27 9:01:45
  14. 【原油贵金属周评】伊朗局势升温,黄金多头跃跃欲试

    原标题:【原油贵金属周评】伊朗局势升温,黄金多头跃跃欲试美国和伊朗的局势继续升温,市场风险情绪上升,避险黄金有向上突破阻力的迹象。原油方面稍显平稳,近期美国和OPEC加大供给及市场需求回落的影响,伊朗局势并未推升油价走强。近期中美贸易谈判摩擦再度升级,美国对中…...

    2024/4/27 17:59:30
  15. 【原油贵金属早评】市场情绪继续恶化,黄金上破

    原标题:【原油贵金属早评】市场情绪继续恶化,黄金上破周初中国针对于美国加征关税的进行的反制措施引发市场情绪的大幅波动,人民币汇率出现大幅的贬值动能,金融市场受到非常明显的冲击。尤其是波动率起来之后,对于股市的表现尤其不安。隔夜美国股市出现明显的下行走势,这…...

    2024/4/25 18:39:16
  16. 【外汇早评】美伊僵持,风险情绪继续升温

    原标题:【外汇早评】美伊僵持,风险情绪继续升温昨日沙特两艘油轮再次发生爆炸事件,导致波斯湾局势进一步恶化,市场担忧美伊可能会出现摩擦生火,避险品种获得支撑,黄金和日元大幅走强。美指受中美贸易问题影响而在低位震荡。继5月12日,四艘商船在阿联酋领海附近的阿曼湾、…...

    2024/4/25 18:39:16
  17. 【原油贵金属早评】贸易冲突导致需求低迷,油价弱势

    原标题:【原油贵金属早评】贸易冲突导致需求低迷,油价弱势近日虽然伊朗局势升温,中东地区几起油船被袭击事件影响,但油价并未走高,而是出于调整结构中。由于市场预期局势失控的可能性较低,而中美贸易问题导致的全球经济衰退风险更大,需求会持续低迷,因此油价调整压力较…...

    2024/4/26 19:03:37
  18. 氧生福地 玩美北湖(上)——为时光守候两千年

    原标题:氧生福地 玩美北湖(上)——为时光守候两千年一次说走就走的旅行,只有一张高铁票的距离~ 所以,湖南郴州,我来了~ 从广州南站出发,一个半小时就到达郴州西站了。在动车上,同时改票的南风兄和我居然被分到了一个车厢,所以一路非常愉快地聊了过来。 挺好,最起…...

    2024/4/26 22:01:59
  19. 氧生福地 玩美北湖(中)——永春梯田里的美与鲜

    原标题:氧生福地 玩美北湖(中)——永春梯田里的美与鲜一觉醒来,因为大家太爱“美”照,在柳毅山庄去寻找龙女而错过了早餐时间。近十点,向导坏坏还是带着饥肠辘辘的我们去吃郴州最富有盛名的“鱼头粉”。说这是“十二分推荐”,到郴州必吃的美食之一。 哇塞!那个味美香甜…...

    2024/4/25 18:39:14
  20. 氧生福地 玩美北湖(下)——奔跑吧骚年!

    原标题:氧生福地 玩美北湖(下)——奔跑吧骚年!让我们红尘做伴 活得潇潇洒洒 策马奔腾共享人世繁华 对酒当歌唱出心中喜悦 轰轰烈烈把握青春年华 让我们红尘做伴 活得潇潇洒洒 策马奔腾共享人世繁华 对酒当歌唱出心中喜悦 轰轰烈烈把握青春年华 啊……啊……啊 两…...

    2024/4/26 23:04:58
  21. 扒开伪装医用面膜,翻六倍价格宰客,小姐姐注意了!

    原标题:扒开伪装医用面膜,翻六倍价格宰客,小姐姐注意了!扒开伪装医用面膜,翻六倍价格宰客!当行业里的某一品项火爆了,就会有很多商家蹭热度,装逼忽悠,最近火爆朋友圈的医用面膜,被沾上了污点,到底怎么回事呢? “比普通面膜安全、效果好!痘痘、痘印、敏感肌都能用…...

    2024/4/25 2:10:52
  22. 「发现」铁皮石斛仙草之神奇功效用于医用面膜

    原标题:「发现」铁皮石斛仙草之神奇功效用于医用面膜丽彦妆铁皮石斛医用面膜|石斛多糖无菌修护补水贴19大优势: 1、铁皮石斛:自唐宋以来,一直被列为皇室贡品,铁皮石斛生于海拔1600米的悬崖峭壁之上,繁殖力差,产量极低,所以古代仅供皇室、贵族享用 2、铁皮石斛自古民间…...

    2024/4/25 18:39:00
  23. 丽彦妆\医用面膜\冷敷贴轻奢医学护肤引导者

    原标题:丽彦妆\医用面膜\冷敷贴轻奢医学护肤引导者【公司简介】 广州华彬企业隶属香港华彬集团有限公司,专注美业21年,其旗下品牌: 「圣茵美」私密荷尔蒙抗衰,产后修复 「圣仪轩」私密荷尔蒙抗衰,产后修复 「花茵莳」私密荷尔蒙抗衰,产后修复 「丽彦妆」专注医学护…...

    2024/4/26 19:46:12
  24. 广州械字号面膜生产厂家OEM/ODM4项须知!

    原标题:广州械字号面膜生产厂家OEM/ODM4项须知!广州械字号面膜生产厂家OEM/ODM流程及注意事项解读: 械字号医用面膜,其实在我国并没有严格的定义,通常我们说的医美面膜指的应该是一种「医用敷料」,也就是说,医用面膜其实算作「医疗器械」的一种,又称「医用冷敷贴」。 …...

    2024/4/27 11:43:08
  25. 械字号医用眼膜缓解用眼过度到底有无作用?

    原标题:械字号医用眼膜缓解用眼过度到底有无作用?医用眼膜/械字号眼膜/医用冷敷眼贴 凝胶层为亲水高分子材料,含70%以上的水分。体表皮肤温度传导到本产品的凝胶层,热量被凝胶内水分子吸收,通过水分的蒸发带走大量的热量,可迅速地降低体表皮肤局部温度,减轻局部皮肤的灼…...

    2024/4/27 8:32:30
  26. 配置失败还原请勿关闭计算机,电脑开机屏幕上面显示,配置失败还原更改 请勿关闭计算机 开不了机 这个问题怎么办...

    解析如下&#xff1a;1、长按电脑电源键直至关机&#xff0c;然后再按一次电源健重启电脑&#xff0c;按F8健进入安全模式2、安全模式下进入Windows系统桌面后&#xff0c;按住“winR”打开运行窗口&#xff0c;输入“services.msc”打开服务设置3、在服务界面&#xff0c;选中…...

    2022/11/19 21:17:18
  27. 错误使用 reshape要执行 RESHAPE,请勿更改元素数目。

    %读入6幅图像&#xff08;每一幅图像的大小是564*564&#xff09; f1 imread(WashingtonDC_Band1_564.tif); subplot(3,2,1),imshow(f1); f2 imread(WashingtonDC_Band2_564.tif); subplot(3,2,2),imshow(f2); f3 imread(WashingtonDC_Band3_564.tif); subplot(3,2,3),imsho…...

    2022/11/19 21:17:16
  28. 配置 已完成 请勿关闭计算机,win7系统关机提示“配置Windows Update已完成30%请勿关闭计算机...

    win7系统关机提示“配置Windows Update已完成30%请勿关闭计算机”问题的解决方法在win7系统关机时如果有升级系统的或者其他需要会直接进入一个 等待界面&#xff0c;在等待界面中我们需要等待操作结束才能关机&#xff0c;虽然这比较麻烦&#xff0c;但是对系统进行配置和升级…...

    2022/11/19 21:17:15
  29. 台式电脑显示配置100%请勿关闭计算机,“准备配置windows 请勿关闭计算机”的解决方法...

    有不少用户在重装Win7系统或更新系统后会遇到“准备配置windows&#xff0c;请勿关闭计算机”的提示&#xff0c;要过很久才能进入系统&#xff0c;有的用户甚至几个小时也无法进入&#xff0c;下面就教大家这个问题的解决方法。第一种方法&#xff1a;我们首先在左下角的“开始…...

    2022/11/19 21:17:14
  30. win7 正在配置 请勿关闭计算机,怎么办Win7开机显示正在配置Windows Update请勿关机...

    置信有很多用户都跟小编一样遇到过这样的问题&#xff0c;电脑时发现开机屏幕显现“正在配置Windows Update&#xff0c;请勿关机”(如下图所示)&#xff0c;而且还需求等大约5分钟才干进入系统。这是怎样回事呢&#xff1f;一切都是正常操作的&#xff0c;为什么开时机呈现“正…...

    2022/11/19 21:17:13
  31. 准备配置windows 请勿关闭计算机 蓝屏,Win7开机总是出现提示“配置Windows请勿关机”...

    Win7系统开机启动时总是出现“配置Windows请勿关机”的提示&#xff0c;没过几秒后电脑自动重启&#xff0c;每次开机都这样无法进入系统&#xff0c;此时碰到这种现象的用户就可以使用以下5种方法解决问题。方法一&#xff1a;开机按下F8&#xff0c;在出现的Windows高级启动选…...

    2022/11/19 21:17:12
  32. 准备windows请勿关闭计算机要多久,windows10系统提示正在准备windows请勿关闭计算机怎么办...

    有不少windows10系统用户反映说碰到这样一个情况&#xff0c;就是电脑提示正在准备windows请勿关闭计算机&#xff0c;碰到这样的问题该怎么解决呢&#xff0c;现在小编就给大家分享一下windows10系统提示正在准备windows请勿关闭计算机的具体第一种方法&#xff1a;1、2、依次…...

    2022/11/19 21:17:11
  33. 配置 已完成 请勿关闭计算机,win7系统关机提示“配置Windows Update已完成30%请勿关闭计算机”的解决方法...

    今天和大家分享一下win7系统重装了Win7旗舰版系统后&#xff0c;每次关机的时候桌面上都会显示一个“配置Windows Update的界面&#xff0c;提示请勿关闭计算机”&#xff0c;每次停留好几分钟才能正常关机&#xff0c;导致什么情况引起的呢&#xff1f;出现配置Windows Update…...

    2022/11/19 21:17:10
  34. 电脑桌面一直是清理请关闭计算机,windows7一直卡在清理 请勿关闭计算机-win7清理请勿关机,win7配置更新35%不动...

    只能是等着&#xff0c;别无他法。说是卡着如果你看硬盘灯应该在读写。如果从 Win 10 无法正常回滚&#xff0c;只能是考虑备份数据后重装系统了。解决来方案一&#xff1a;管理员运行cmd&#xff1a;net stop WuAuServcd %windir%ren SoftwareDistribution SDoldnet start WuA…...

    2022/11/19 21:17:09
  35. 计算机配置更新不起,电脑提示“配置Windows Update请勿关闭计算机”怎么办?

    原标题&#xff1a;电脑提示“配置Windows Update请勿关闭计算机”怎么办&#xff1f;win7系统中在开机与关闭的时候总是显示“配置windows update请勿关闭计算机”相信有不少朋友都曾遇到过一次两次还能忍但经常遇到就叫人感到心烦了遇到这种问题怎么办呢&#xff1f;一般的方…...

    2022/11/19 21:17:08
  36. 计算机正在配置无法关机,关机提示 windows7 正在配置windows 请勿关闭计算机 ,然后等了一晚上也没有关掉。现在电脑无法正常关机...

    关机提示 windows7 正在配置windows 请勿关闭计算机 &#xff0c;然后等了一晚上也没有关掉。现在电脑无法正常关机以下文字资料是由(历史新知网www.lishixinzhi.com)小编为大家搜集整理后发布的内容&#xff0c;让我们赶快一起来看一下吧&#xff01;关机提示 windows7 正在配…...

    2022/11/19 21:17:05
  37. 钉钉提示请勿通过开发者调试模式_钉钉请勿通过开发者调试模式是真的吗好不好用...

    钉钉请勿通过开发者调试模式是真的吗好不好用 更新时间:2020-04-20 22:24:19 浏览次数:729次 区域: 南阳 > 卧龙 列举网提醒您:为保障您的权益,请不要提前支付任何费用! 虚拟位置外设器!!轨迹模拟&虚拟位置外设神器 专业用于:钉钉,外勤365,红圈通,企业微信和…...

    2022/11/19 21:17:05
  38. 配置失败还原请勿关闭计算机怎么办,win7系统出现“配置windows update失败 还原更改 请勿关闭计算机”,长时间没反应,无法进入系统的解决方案...

    前几天班里有位学生电脑(windows 7系统)出问题了&#xff0c;具体表现是开机时一直停留在“配置windows update失败 还原更改 请勿关闭计算机”这个界面&#xff0c;长时间没反应&#xff0c;无法进入系统。这个问题原来帮其他同学也解决过&#xff0c;网上搜了不少资料&#x…...

    2022/11/19 21:17:04
  39. 一个电脑无法关闭计算机你应该怎么办,电脑显示“清理请勿关闭计算机”怎么办?...

    本文为你提供了3个有效解决电脑显示“清理请勿关闭计算机”问题的方法&#xff0c;并在最后教给你1种保护系统安全的好方法&#xff0c;一起来看看&#xff01;电脑出现“清理请勿关闭计算机”在Windows 7(SP1)和Windows Server 2008 R2 SP1中&#xff0c;添加了1个新功能在“磁…...

    2022/11/19 21:17:03
  40. 请勿关闭计算机还原更改要多久,电脑显示:配置windows更新失败,正在还原更改,请勿关闭计算机怎么办...

    许多用户在长期不使用电脑的时候&#xff0c;开启电脑发现电脑显示&#xff1a;配置windows更新失败&#xff0c;正在还原更改&#xff0c;请勿关闭计算机。。.这要怎么办呢&#xff1f;下面小编就带着大家一起看看吧&#xff01;如果能够正常进入系统&#xff0c;建议您暂时移…...

    2022/11/19 21:17:02
  41. 还原更改请勿关闭计算机 要多久,配置windows update失败 还原更改 请勿关闭计算机,电脑开机后一直显示以...

    配置windows update失败 还原更改 请勿关闭计算机&#xff0c;电脑开机后一直显示以以下文字资料是由(历史新知网www.lishixinzhi.com)小编为大家搜集整理后发布的内容&#xff0c;让我们赶快一起来看一下吧&#xff01;配置windows update失败 还原更改 请勿关闭计算机&#x…...

    2022/11/19 21:17:01
  42. 电脑配置中请勿关闭计算机怎么办,准备配置windows请勿关闭计算机一直显示怎么办【图解】...

    不知道大家有没有遇到过这样的一个问题&#xff0c;就是我们的win7系统在关机的时候&#xff0c;总是喜欢显示“准备配置windows&#xff0c;请勿关机”这样的一个页面&#xff0c;没有什么大碍&#xff0c;但是如果一直等着的话就要两个小时甚至更久都关不了机&#xff0c;非常…...

    2022/11/19 21:17:00
  43. 正在准备配置请勿关闭计算机,正在准备配置windows请勿关闭计算机时间长了解决教程...

    当电脑出现正在准备配置windows请勿关闭计算机时&#xff0c;一般是您正对windows进行升级&#xff0c;但是这个要是长时间没有反应&#xff0c;我们不能再傻等下去了。可能是电脑出了别的问题了&#xff0c;来看看教程的说法。正在准备配置windows请勿关闭计算机时间长了方法一…...

    2022/11/19 21:16:59
  44. 配置失败还原请勿关闭计算机,配置Windows Update失败,还原更改请勿关闭计算机...

    我们使用电脑的过程中有时会遇到这种情况&#xff0c;当我们打开电脑之后&#xff0c;发现一直停留在一个界面&#xff1a;“配置Windows Update失败&#xff0c;还原更改请勿关闭计算机”&#xff0c;等了许久还是无法进入系统。如果我们遇到此类问题应该如何解决呢&#xff0…...

    2022/11/19 21:16:58
  45. 如何在iPhone上关闭“请勿打扰”

    Apple’s “Do Not Disturb While Driving” is a potentially lifesaving iPhone feature, but it doesn’t always turn on automatically at the appropriate time. For example, you might be a passenger in a moving car, but your iPhone may think you’re the one dri…...

    2022/11/19 21:16:57