cas单点登录原理与实现(整合springsecurity)

article/2025/9/4 2:56:49

一、cas原理分析

SSO英文全称Single Sign On,单点登录。SSO是在多个应用系统中,用户只需要登录一次就可以访问所有相互信任的应用系统。CAS是一种基于http协议的B/S应用系统单点登录实现方案,认识CAS之前首先要熟悉http协议、Session与Cookie等Web开发基本知识。

1.1 Cas登录:
两次前端跳转、一次后端验证

1.1.1 首次访问应用A

第一次跳转:

客户端访问应用系统A,应用系统判断Session发现未登录,返回302跳转到sso登录页面,并传递service参数给sso,该service参数有两个作用:(回跳、认证)
1、 service一般传递应用系统url地址,用于sso认证通过后回跳到应用系统A;
2、service参数同时会被cas服务端的作为cas客户端的唯一标记记录下来,用于后期匹配相应的认证凭据;

第二次跳转:

浏览器显示登录页面,用户输入账号密码登录成功后,sso会返回302跳转回到原来请求的应用系统页面,并携带ticket参数,作为认证票据,同时通过Set-Cookie向浏览器记录TGT,(TGT的作用将在下一个应用系统需要登录的时候体现出作用,是避免重复登录的关键)

后台进行一次票据验证:

应用系统接收到带有ticket的请求后,从后台直接向sso服务器发起一个http请求,将service和ticket作为参数,用于验证ticket的有效性;如果ticket有效,sso服务器将返回该ticket对应的登录用户名。

图例:

在这里插入图片描述
1.1.2 访问A登陆后首次访问应用B

访问应用B系统,根据session判断未登录,重定向到CAS Serve,根据Cookie里面的TGT找到对应的用户信息,携带ticket重定向会应用系统B,应用系统B接收到带有ticket的请求后,从后台直接向sso服务器发起一个http请求,将service和ticket作为参数,用于验证ticket的有效性;如果ticket有效,sso服务器将返回该ticket对应的登录用户名

二、实现cas客户端

yaml配置:

security:cas:server:host: https://localhost:8443/cas  #cas服务器的地址login: ${security.cas.server.host}/login  #单点登录地址logout: ${security.cas.server.host}/logout  #单点登出店址service:webHost: http://localhost:8090  #应用系统的地址login: /login       #应用系统的登录入口logout: /logout     #应用系统的登出入口

2.1 参数配置类:

  • CAS认证中心参数配置类
import lombok.Data;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Configuration;@Data
@Configuration
public class CasServerConfig {@Value("${security.cas.server.host}")private String host;@Value("${security.cas.server.login}")private String login;@Value("${security.cas.server.logout}")private String logout;
}
  • 应用服务器参数配置类
import lombok.Data;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Configuration;@Data
@Configuration
public class CasServiceConfig {@Value("${security.cas.service.webHost}")private String webHost;@Value("${security.cas.service.login}")private String login;@Value("${security.cas.service.logout}")private String logout;private Boolean sendRenew = false;}

2.2 CAS配置

  • CAS配置类
import org.jasig.cas.client.validation.Cas20ServiceTicketValidator;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.cas.ServiceProperties;
import org.springframework.security.cas.authentication.CasAssertionAuthenticationToken;
import org.springframework.security.cas.authentication.CasAuthenticationProvider;
import org.springframework.security.cas.web.CasAuthenticationEntryPoint;
import org.springframework.security.cas.web.CasAuthenticationFilter;
import org.springframework.security.core.userdetails.AuthenticationUserDetailsService;
import org.springframework.security.web.authentication.logout.LogoutFilter;@Configuration
public class SecurityConfiguration {@Autowiredprivate CasServerConfig casServerConfig;@Autowired private CasServiceConfig casServiceConfig;@Beanpublic ServiceProperties serviceProperties() {ServiceProperties serviceProperties = new ServiceProperties();serviceProperties.setService(this.casServiceConfig.getWebHost() + this.casServiceConfig.getLogin()); //回跳地址serviceProperties.setSendRenew(this.casServiceConfig.getSendRenew());//是否敏感,即登录不同的应用系统是否还要重新登录serviceProperties.setAuthenticateAllArtifacts(true); //是否对没有ticket的访问需要验证return serviceProperties;}/**** CAS认证过滤器* @param authenticationManager* @param serviceProperties* @return*/@Beanpublic CasAuthenticationFilter casAuthenticationFilter(AuthenticationManager authenticationManager, ServiceProperties serviceProperties) {CasAuthenticationFilter casAuthenticationFilter = new CasAuthenticationFilter();casAuthenticationFilter.setAuthenticationManager(authenticationManager);casAuthenticationFilter.setServiceProperties(serviceProperties);casAuthenticationFilter.setFilterProcessesUrl(this.casServiceConfig.getLogin());casAuthenticationFilter.setContinueChainBeforeSuccessfulAuthentication(false);casAuthenticationFilter.setAuthenticationSuccessHandler(new UrlAuthenticationSuccessHandler("/"));return casAuthenticationFilter;}/*** CAS入口* @param serviceProperties* @return*/@Beanpublic CasAuthenticationEntryPoint casAuthenticationEntryPoint(ServiceProperties serviceProperties) {CasAuthenticationEntryPoint entryPoint = new CasAuthenticationEntryPoint();entryPoint.setLoginUrl(this.casServerConfig.getLogin());entryPoint.setServiceProperties(serviceProperties);return entryPoint;}/*** CASticket验证* @return*/@Beanpublic Cas20ServiceTicketValidator cas20ServiceTicketValidator() {return new Cas20ServiceTicketValidator(this.casServerConfig.getHost());}@Beanpublic CasAuthenticationProvider casAuthenticationProvider(AuthenticationUserDetailsService<CasAssertionAuthenticationToken> userDetailsService,ServiceProperties serviceProperties,Cas20ServiceTicketValidator ticketValidator) {CasAuthenticationProvider provider = new CasAuthenticationProvider();provider.setKey("casProvider");provider.setServiceProperties(serviceProperties);provider.setTicketValidator(ticketValidator);provider.setAuthenticationUserDetailsService(userDetailsService);//自己的userDetailServicereturn provider;}/*** 登出过滤器* @return*/@Beanpublic LogoutFilter logoutFilter() {String logoutRedirectPath =this.casServerConfig.getLogout() + "?service=" + this.casServiceConfig.getWebHost();LogoutFilter logoutFilter =new LogoutFilter(logoutRedirectPath, new CasSecurityContextLogoutHandler());logoutFilter.setFilterProcessesUrl(this.casServiceConfig.getLogout());return logoutFilter;}
}
  • 认证成功处理类
import lombok.extern.slf4j.Slf4j;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.web.authentication.SimpleUrlAuthenticationSuccessHandler;
import org.springframework.util.StringUtils;import javax.servlet.ServletException;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;
import java.util.Collection;@Slf4j(topic = "c.successHandler")
public class UrlAuthenticationSuccessHandler extends SimpleUrlAuthenticationSuccessHandler {public UrlAuthenticationSuccessHandler() {super();}public UrlAuthenticationSuccessHandler(String defaultTargetUrl) {super(defaultTargetUrl);}/*** 认证成功后* @param request* @param response* @param authentication* @throws IOException* @throws ServletException*/@Overridepublic void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException {super.onAuthenticationSuccess(request, response, authentication);}/***返回一个认证成功后的路径* @param request* @param response* @return*/@Overrideprotected String determineTargetUrl(HttpServletRequest request, HttpServletResponse response) {StringBuffer targetUrl = null;//根据自己需求写HttpSession session = request.getSession();targetUrl = (StringBuffer) session.getAttribute("REQUEST_URL");log.debug("目标路径为{}", targetUrl);return targetUrl.toString();}
}
  • 自定义过滤器(存储要访问的路径)
mport com.hzx.hzxy_grid.domain.SecurityUser;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Component;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.Collection;@Component
@Slf4j
public class HttpParamsFilter implements Filter {@Overridepublic void init(FilterConfig filterConfig) throws ServletException {}@Overridepublic void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain chain)throws IOException, ServletException {final HttpServletRequest request = (HttpServletRequest) servletRequest;final HttpServletResponse response = (HttpServletResponse) servletResponse;HttpSession session = request.getSession();StringBuffer requestURL = request.getRequestURL();log.info("请求地址:" + requestURL);chain.doFilter(request, response);}@Overridepublic void destroy() {}
}
  • 单点登出过滤器
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContext;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.web.authentication.logout.LogoutHandler;
import org.springframework.util.Assert;import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;public class CasSecurityContextLogoutHandler implements LogoutHandler {protected final Log logger = LogFactory.getLog(this.getClass());private boolean invalidateHttpSession = true;private boolean clearAuthentication = true;public CasSecurityContextLogoutHandler() {}public void logout(HttpServletRequest request, HttpServletResponse response, Authentication authentication) {Assert.notNull(request, "HttpServletRequest required");if (this.invalidateHttpSession) {HttpSession session = request.getSession(false);if (session != null) {this.logger.debug("Invalidating session: " + session.getId());//发布退出登录事件,自己增加,监听此事件处理一些事情session.invalidate(); //session失效
//        LogoutEvent event = new LogoutEvent();
//        event.setSessionId(session.getId());
//        EventPublisherUtil.publish(event);}}if (this.clearAuthentication) {SecurityContext context = SecurityContextHolder.getContext();context.setAuthentication((Authentication)null);}SecurityContextHolder.clearContext();}public boolean isInvalidateHttpSession() {return this.invalidateHttpSession;}public void setInvalidateHttpSession(boolean invalidateHttpSession) {this.invalidateHttpSession = invalidateHttpSession;}public void setClearAuthentication(boolean clearAuthentication) {this.clearAuthentication = clearAuthentication;}
}
  • springsecurity配置类
import com.hzx.hzxy_grid.config.custom.CustomFilter;
import com.hzx.hzxy_grid.config.custom.CustomUrlDecisionManager;
import com.hzx.hzxy_grid.handler.CustomizeAccessDeniedHandler;
import org.jasig.cas.client.session.SingleSignOutFilter;
import org.jasig.cas.client.session.SingleSignOutHttpSessionListener;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.security.SecurityProperties;
import org.springframework.boot.web.servlet.ServletListenerRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.annotation.Order;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.cas.authentication.CasAuthenticationProvider;
import org.springframework.security.cas.web.CasAuthenticationEntryPoint;
import org.springframework.security.cas.web.CasAuthenticationFilter;
import org.springframework.security.config.BeanIds;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.builders.WebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.web.access.intercept.FilterSecurityInterceptor;
import org.springframework.security.web.authentication.logout.LogoutFilter;
import org.springframework.web.cors.CorsUtils;@Configuration
@Order(SecurityProperties.BASIC_AUTH_ORDER)
public class CasWebSecurityConfiguration extends WebSecurityConfigurerAdapter {@Autowiredprivate CasAuthenticationEntryPoint casAuthenticationEntryPoint;@Autowiredprivate CasAuthenticationProvider casAuthenticationProvider;@Autowiredprivate CasAuthenticationFilter casAuthenticationFilter;@Autowiredprivate LogoutFilter logoutFilter;@Autowiredprivate CasServerConfig casServerConfig;@Autowiredprivate HttpParamsFilter httpParamsFilter;@Autowiredprivate CustomFilter customFilter;@Autowiredprivate CustomUrlDecisionManager customUrlDecisionManager;@Overridepublic void configure(WebSecurity web) throws Exception {web.ignoring().antMatchers("/swagger-resources/**","/swagger-ui.html","/v2/api-docs","/webjars/**","/v3/api-docs",
//                "/login","/static/**","/api/**");super.configure(web);}@Overrideprotected void configure(HttpSecurity http) throws Exception {http.headers().frameOptions().disable();http.csrf().disable();http.authorizeRequests().requestMatchers(CorsUtils::isPreFlightRequest).permitAll().anyRequest().authenticated(); // 所有资源都需要登陆后才可以访问。http.logout().permitAll(); // 不拦截注销http.exceptionHandling().authenticationEntryPoint(casAuthenticationEntryPoint).accessDeniedHandler(new CustomizeAccessDeniedHandler());// 单点注销的过滤器,必须配置在SpringSecurity的过滤器链中,如果直接配置在Web容器中,貌似是不起作用的。我自己的是不起作用的。SingleSignOutFilter singleSignOutFilter = new SingleSignOutFilter();singleSignOutFilter.setArtifactParameterName(this.casServerConfig.getHost());http.addFilter(casAuthenticationFilter).addFilterBefore(logoutFilter, LogoutFilter.class).addFilterBefore(singleSignOutFilter, CasAuthenticationFilter.class);http.addFilterBefore(httpParamsFilter, FilterSecurityInterceptor.class);http.addFilterBefore(filterSecurityInterceptor(), FilterSecurityInterceptor.class);http.antMatcher("/**");}/*** 权限拦截** @return* @throws Exception*/public FilterSecurityInterceptor filterSecurityInterceptor() throws Exception {FilterSecurityInterceptor filterSecurityInterceptor = new FilterSecurityInterceptor();filterSecurityInterceptor.setSecurityMetadataSource(customFilter);filterSecurityInterceptor.setAuthenticationManager(authenticationManager());filterSecurityInterceptor.setAccessDecisionManager(customUrlDecisionManager);return filterSecurityInterceptor;}@Autowiredpublic void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {auth.authenticationProvider(casAuthenticationProvider);}@Beanpublic ServletListenerRegistrationBean<SingleSignOutHttpSessionListener>singleSignOutHttpSessionListener() {ServletListenerRegistrationBean<SingleSignOutHttpSessionListener> servletListenerRegistrationBean =new ServletListenerRegistrationBean<>();servletListenerRegistrationBean.setListener(new SingleSignOutHttpSessionListener());return servletListenerRegistrationBean;}/*** AuthenticationManager** @return* @throws Exception*/@Bean(name = BeanIds.AUTHENTICATION_MANAGER)@Overridepublic AuthenticationManager authenticationManagerBean() throws Exception {return super.authenticationManagerBean();}
}
  • CustomFilter类
/*** 根据访问的路径判断出所需的角色*/@Component
@Slf4j(topic = "c.CustomUrl")
public class CustomFilter implements FilterInvocationSecurityMetadataSource {//路径匹配private AntPathMatcher antPathMatcher = new AntPathMatcher();@Autowiredprivate MenuService menuService;@Overridepublic Collection<ConfigAttribute> getAttributes(Object o) throws IllegalArgumentException {// 获取请求的UrlString requestUrl = ((FilterInvocation) o).getRequestUrl();List<Menu> menuWithRoles = menuService.getMenuWithRoles();for (Menu menu : menuWithRoles) {//访问的路径是否跟菜单的里的路径相同if (antPathMatcher.match(menu.getUrl(), requestUrl)) {String[] roles = menu.getRoleList().stream().map(Role::getRoleName).toArray(String[]::new);log.info("需要的权限为{}", roles);System.out.println(roles);return SecurityConfig.createList(roles);}}return SecurityConfig.createList("ROLE_LOGIN");}@Overridepublic Collection<ConfigAttribute> getAllConfigAttributes() {return null;}@Overridepublic boolean supports(Class<?> aClass) {return false;}
}
  • CustomDecisionManager
@Component
public class CustomUrlDecisionManager implements AccessDecisionManager {@Overridepublic void decide(Authentication authentication, Object o, Collection<ConfigAttribute> collection) throws AccessDeniedException, InsufficientAuthenticationException {for (ConfigAttribute configAttribute : collection) {String needRole = configAttribute.getAttribute();if ("ROLE_LOGIN".equals(needRole)) {if (authentication instanceof AnonymousAuthenticationToken) {throw new AccessDeniedException("用户未登录,请登录");} elsereturn;}//判断是否有对应的权限信息Collection<? extends GrantedAuthority> authorities = authentication.getAuthorities();for (GrantedAuthority authority : authorities) {if(authority.getAuthority().equals(needRole))return;}}throw new AccessDeniedException("用户无权限访问");}@Overridepublic boolean supports(ConfigAttribute configAttribute) {return false;}@Overridepublic boolean supports(Class<?> aClass) {return false;}
}
  • 未授权无法访问CustomizeAccessDeniedHandler
import com.hzx.hzxy_grid.domain.R;
import com.hzx.hzxy_grid.enums.Status;
import com.hzx.hzxy_grid.util.ResponseUtil;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.security.web.access.AccessDeniedHandler;import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;/*** 未授权,用户无权访问*/public class CustomizeAccessDeniedHandler implements AccessDeniedHandler {@Overridepublic void handle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, AccessDeniedException e) throws IOException, ServletException {ResponseUtil.out(httpServletResponse,R.error().status(Status.UNAUTHORIZED));}
}
  • AuthenticationUserDetailsService
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.hzx.hzxy_grid.domain.Admin;
import com.hzx.hzxy_grid.domain.Role;
import com.hzx.hzxy_grid.domain.SecurityUser;
import com.hzx.hzxy_grid.mapper.AdminMapper;
import com.hzx.hzxy_grid.mapper.RoleMapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.security.cas.authentication.CasAssertionAuthenticationToken;
import org.springframework.security.core.userdetails.AuthenticationUserDetailsService;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service;import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;@Slf4j(topic = "c.UserDetailServiceImpl")
@Service
public class MyUserDetailServiceImpl implements AuthenticationUserDetailsService<CasAssertionAuthenticationToken> {@Autowiredprivate RoleMapper roleMapper;@Autowiredprivate AdminMapper adminMapper;@Autowiredprivate RedisTemplate redisTemplate;@Overridepublic UserDetails loadUserDetails(CasAssertionAuthenticationToken token) throws UsernameNotFoundException {String username = token.getName();Admin admin = adminMapper.selectOne(new LambdaQueryWrapper<Admin>().eq(Admin::getUsername, username));log.info("admin:{}", admin);if (admin == null)throw new UsernameNotFoundException("用户名不存在");SecurityUser securityUser = new SecurityUser();List<String> permissionList = null;//如果redis不存在该用户的权限if (!redisTemplate.hasKey("permission_" + admin.getUid())) {//添加权限List<Role> roleList = roleMapper.getRolesByAdminId(admin.getUid());permissionList = roleList.stream().map(role -> role.getRoleName()).collect(Collectors.toList());securityUser.setPermissionValueList(permissionList);securityUser.setCurrentUserInfo(admin);log.info("从数据库中查询到用户的权限为{}", permissionList);} else {permissionList = (List<String>) redisTemplate.opsForValue().get("permission_" + admin.getUid());log.info("从redis中查询到用户的权限为{}",permissionList);}securityUser.setPermissionValueList(permissionList);securityUser.setCurrentUserInfo(admin);log.info("用户的权限为{}", permissionList);return securityUser;}
}
  • SecurityUser
import lombok.Data;
import org.springframework.security.core.CredentialsContainer;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.util.StringUtils;import java.util.ArrayList;
import java.util.Collection;
import java.util.List;@Data
public class SecurityUser implements UserDetails, CredentialsContainer {//当前登录用户private transient Admin currentUserInfo;//当前权限private List<String> permissionValueList;public SecurityUser() {}public SecurityUser(Admin admin) {if (admin != null) {this.currentUserInfo = admin;}}@Overridepublic Collection<? extends GrantedAuthority> getAuthorities() {Collection<GrantedAuthority> authorities = new ArrayList<>();for(String permissionValue : permissionValueList) {if(StringUtils.isEmpty(permissionValue)) continue;SimpleGrantedAuthority authority = new SimpleGrantedAuthority(permissionValue);authorities.add(authority);}return authorities;}@Overridepublic String getPassword() {return currentUserInfo.getPassword();}@Overridepublic String getUsername() {return currentUserInfo.getUsername();}@Overridepublic boolean isAccountNonExpired() {return true;}@Overridepublic boolean isAccountNonLocked() {return true;}@Overridepublic boolean isCredentialsNonExpired() {return true;}@Overridepublic boolean isEnabled() {return true;}@Overridepublic void eraseCredentials() {}
}

http://chatgpt.dhexx.cn/article/FAfXvqrZ.shtml

相关文章

CAS 实现单点登录(SSO)原理

原地址&#xff1a;https://blog.csdn.net/hejingyuan6/article/details/44277023 一、概念&#xff1a;     单点登录&#xff08;Single Sign On&#xff09;&#xff1a;简称为SSO&#xff0c;是目前比较流行的企业业务整合的解决方案之一。SSO的定义是在多个应用系统中…

CAS单点登录原理

转载地址&#xff1a;转载博客 1、基于Cookie的单点登录的回顾 基于Cookie的单点登录核心原理&#xff1a; 将用户名密码加密之后存于Cookie中&#xff0c;之后访问网站时在过滤器&#xff08;filter&#xff09;中校验用户权限&#xff0c;如果没有权限则从Cookie中取出用户…

python iloc函数_如何使用python语言中pandas模块中的iloc方法

在python语言中,pandas模块中的iloc方法,可以截取矩阵,获取部分矩阵元素、行和列。下面利用实例说明iloc方法的用法,操作如下: 工具/原料 python pycharm 截图工具 方法/步骤 1 打开pycharm工具,新建python文件,导入numpy和pandas,调用DataFrame生成矩阵 2 保存…

python iloc和loc切片

文章目录 一、含正负号的下标二、loc和iloc1. 利用loc、iloc提取行数据2. 利用loc、iloc提取列数据3.利用loc、iloc提取指定行、指定列数据4.利用loc、iloc提取所有数据5.利用loc函数&#xff0c;根据某个数据来提取数据所在的行 一、含正负号的下标 正下标从0开始&#xff0c;…

Pandas之iloc、loc

除了最基本的筛选外&#xff0c;例&#xff1a;data[‘A’] 还有loc、iloc、ix&#xff08;已不推荐使用&#xff09; 我对它们的区分&#xff0c;说loc&#xff08;location&#xff09;&#xff0c;在教室里找不认识的同学的位置一样的&#xff0c;找人肯定要知道名字或者身…

iloc函数使用方法

iloc函数使用方法 iloc[ : , : ] 前面的冒号就是取行数&#xff0c;后面的冒号是取列数 左闭右开原则 举个例子来理解切片的概念。 animals[2&#xff1b;5] 其中2,5都是指的元素的索引&#xff0c;索引从0开始&#xff0c;表示从第3个元素到第四个元素&#xff08;前开后闭…

Pandas loc与iloc

先来看一下示例&#xff1a; #!/usr/bin/python import pandas as pd# 三个字段 name, site, age nme ["Google", "Runoob", "Taobao", "Wiki"] st ["www.google.com", "www.runoob.com", "www.taobao.co…

iloc函数

iloc函数 注意&#xff1a;以 **&#xff0c;**为分界 这样看更直观一点 原文链接&#xff1a;iloc

Python学习.iloc和.loc区别、联系与用法

最近接触到数据科学&#xff0c;需要对一些数据表进行分析&#xff0c;观察到代码中一会出现loc一会又出现iloc&#xff0c;下面对两者的用法给出我的一些理解。 1.联系 (1)操作对象相同&#xff1a;loc和iloc都是对DataFrame类型进行操作&#xff1b; (2)完成目的相同&…

Pandas中的loc与iloc用法详解

1.基本简介 1.1 loc与iloc基本含义 loc函数&#xff1a;通过行索引 “Index” 中的具体值来取行数据&#xff08;如取"Index"为"A"的行&#xff09; iloc函数&#xff1a;通过行号来取行数据&#xff08;如取第二行的数据&#xff09; 注&#xff1a;loc是…

JavaScript鼠标移动事件

下面我们来看一个JavaScript鼠标移动选择器时发生改变的列子&#xff0c;图1是它的一个简单的布局&#xff0c; 接下来是它的css部分和js部分&#xff0c;js部分很简单 最后的效果图就出来了

js——设置鼠标悬停事件

鼠标悬停前后 function HoverAndMouseout(){$(".zhangjie").hover(function () {$(this).css({ "width": "500px" });//移上宽度变为500});$(".zhangjie").mouseout(function () {$(this).css({ "width": "170px"…

前台JS:通过Hover(鼠标悬停事件)动态悬浮显示DIV的ID

HTML代码&#xff1a;定义两个DIV并设置大小宽度 <div id"Div1" class"div-list" style"width:20px; height:50px; border:1px solid #F00"><a>DIV1</a></div><div id"Div2" class"div-list1" …

[前端] js鼠标停留事件

在写某个网页作业时&#xff0c;要用到这个基本技能&#xff0c;就是鼠标放到某一选项上变个色&#xff0c;移开后又变回来。 这个在网页中很常见&#xff0c;实现也很简单&#xff0c;写一个小的例子&#xff0c;放在这里方便以后作为模板用。 <!DOCTYPE html PUBLIC "…

jquery的鼠标悬停与移出事件

需求&#xff1a; 实现鼠标悬停在div标签时&#xff0c;背景变为蓝色&#xff0c;字体变红变大&#xff0c;鼠标离开后 背景变白&#xff0c;字体变小 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta nam…

JavaScript事件 鼠标事件

JavaScript事件&#xff0c;事件就是文档或浏览器窗口中发生的一些特定的交互瞬间。 JavaScript 与 HTML 之间的交互是通过事件实现的。对于 Web 应用来说&#xff0c;有下面这些代 表性的事件&#xff1a;单击事件、鼠标移入移出事件、键盘按下/弹起事件等等。 鼠标事件&…

JavaScript 鼠标移动事件

今天我要分享的JavaScript鼠标移动事件的知识点 1.首先准备一个文件夹和一张GIF的动图&#xff0c;打开VS Code&#xff0c;新建一个文件,CtrlS保存文件&#xff0c;输入文件名&#xff0c;文本类型设置成HTML&#xff0c;如下图所示&#xff1b; 2.在文档里输入英文状态下的感…

js 鼠标按下并移动事件

html源码&#xff1a; <divonMouseDown{(e) >fn1(e)}onMouseUp{(e)>fn2(e)}>内容</div> js源码 fn1(event) > { //鼠标按下事件console.log(onMouseDown, event); //鼠标按下时移动鼠标事件&#xff08;鼠标未抬起&#xff09;document.onmousemove fun…

JS小技巧:鼠标悬停事件

简单的JS悬停图片变换 不多bb先看效果图 可以看到鼠标悬停在不同的标题上时&#xff0c;下方的图片会产生相应变换 代码如下 <!DOCTYPE html> <html><head><meta charset"UTF-8"><title></title><style>* {margin: 0;p…