范文健康探索娱乐情感热点
投稿投诉
热点动态
科技财经
情感日志
励志美文
娱乐时尚
游戏搞笑
探索旅游
历史星座
健康养生
美丽育儿
范文作文
教案论文
国学影视

腾讯大佬单点登录系统使用SpringSecurity的权限功能

  单点登录系统使用Spring Security的权限功能背景
  在配置中心增加权限功能 目前配置中心已经包含了单点登录功能,可以通过统一页面进行登录,登录完会将用户写入用户表 RBAC的用户、角色、权限表CRUD、授权等都已经完成 希望不用用户再次登录,就可以使用SpringSecurity的权限控制 Spring Security
  Spring Security最主要的两个功能: 认证和授权
  功能
  解决的问题
  Spring Security中主要类
  认证(Authentication)
  你是谁
  AuthenticationManager
  授权(Authorization)
  你可以做什么
  AuthorizationManager 实现
  在这先简单了解一下Spring Security的架构是怎样的,如何可以认证和授权的
  过滤器 大家应该都了解,这属于Servlet的范畴,Servlet 过滤器可以动态地拦截请求和响应,以变换或使用包含在请求或响应中的信息
  DelegatingFilterProxy 是一个属于Spring Security的过滤器
  通过这个过滤器,Spring Security就可以从Request中获取URL来判断是不是需要认证才能访问,是不是得拥有特定的权限才能访问。 已经有了单点登录页面,Spring Security怎么登录,不登录可以拿到权限吗
  Spring Security官方文档-授权架构中这样说,GrantedAuthority(也就是拥有的权限)被AuthenticationManager写入Authentication对象,后而被AuthorizationManager用来做权限认证
  The GrantedAuthority objects are inserted into the Authentication object by the AuthenticationManager and are later read by either the AuthorizationManager when making authorization decisions.
  为了解决我们的问题,即使我只想用权限认证功能,也得造出一个Authentication,先看下这个对象:Authentication
  Authentication包含三个字段:principal,代表用户credentials,用户密码authorities,拥有的权限
  有两个作用:AuthenticationManager的入参,仅仅是用来存用户的信息,准备去认证AuthenticationManager的出参,已经认证的用户信息,可以从SecurityContext获取
  SecurityContext和SecurityContextHolder用来存储Authentication, 通常是用了线程全局变量ThreadLocal, 也就是认证完成把Authentication放入SecurityContext,后续在整个同线程流程中都可以获取认证信息,也方便了认证继续分析
  看到这可以得到,要实现不登录的权限认证,只需要手动造一个Authentication,然后放入SecurityContext就可以了,先尝试一下,大概流程是这样,在每个请求上获取sso登录的用户读取用户、角色、权限写入Authentication将Authentication写入SecurityContext请求完毕时将SecurityContext清空,因为是ThreadLocal的,不然可能会被别的用户用到同时Spring Security的配置中是对所有的url都允许访问的
  加了一个过滤器,代码如下:import javax.servlet.*; import javax.servlet.annotation.WebFilter; import javax.servlet.http.HttpServletRequest; import java.io.IOException; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.stream.Collectors;  @WebFilter( urlPatterns = "/*", filterName = "reqResFilter" ) public class ReqResFilter implements Filter{  	@Autowired 	private SSOUtils ssoUtils; 	@Autowired 	private UserManager userManager; 	@Autowired 	private RoleManager roleManager;  	@Override 	public void init( FilterConfig filterConfig ) throws ServletException{  	}  	@Override 	public void doFilter( ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain ) 			throws IOException, ServletException{ 		setAuthentication(servletRequest); 		filterChain.doFilter( servletRequest, servletResponse ); 		clearAuthentication(); 	}  	@Override 	public void destroy(){  	}  	private void setAuthentication( ServletRequest request ){  		Map data; 		try{ 			data = ssoUtils.getLoginData( ( HttpServletRequest )request ); 		} 		catch( Exception e ){ 			data = new HashMap<>(); 			data.put( "name", "visitor" ); 		} 		String username = data.get( "name" ); 		if( username != null ){ 			userManager.findAndInsert( username ); 		} 		List userRole = userManager.findUserRole( username ); 		List roleIds = userRole.stream().map( Role::getId ).collect( Collectors.toList() ); 		List rolePermission = roleManager.findRolePermission( roleIds ); 		List authorities = rolePermission.stream().map( one -> new SimpleGrantedAuthority( one.getName() ) ).collect( 				Collectors.toList() );  		UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken( username, "", authorities ); 		SecurityContextHolder.getContext().setAuthentication( authenticationToken ); 	}  	private void clearAuthentication(){  		SecurityContextHolder.clearContext(); 	} }
  从日志可以看出,Principal: visitor,当访问未授权的接口被拒绝了16:04:07.429 [http-nio-8081-exec-9] DEBUG org.springframework.security.access.intercept.aopalliance.MethodSecurityInterceptor - Previously Authenticated: org.springframework.security.authentication.UsernamePasswordAuthenticationToken@cc4c6ea0: Principal: visitor; Credentials: [PROTECTED]; Authenticated: true; Details: null; Granted Authorities: CHANGE_USER_ROLE, CHANGE_ROLE_PERMISSION, ROLE_ADD ... org.springframework.security.access.AccessDeniedException: 不允许访问 结论
  不登录是可以使用Spring Security的权限,从功能上是没有问题的,但存在一些别的问题性能问题,每个请求都需要请求用户角色权限数据库,当然可以利用缓存优化我们写的过滤器其实也是Spring Security做的事,除此之外,它做了更多的事,比如结合HttpSession, Remember me这些功能
  我们可以采取另外一种做法,对用户来说只登录一次就行,我们仍然是可以手动用代码再去登录一次Spring Security的如何手动登录Spring Security
  How to login user from java code in Spring Security? 从这篇文章从可以看到,只要通过以下代码即可	private void loginInSpringSecurity( String username, String password ){  		UsernamePasswordAuthenticationToken loginToken = new UsernamePasswordAuthenticationToken( username, password ); 		Authentication authenticatedUser = authenticationManager.authenticate( loginToken ); 		SecurityContextHolder.getContext().setAuthentication( authenticatedUser ); 	}
  和上面我们直接拿已经认证过的用户对比,这段代码让Spring Security来执行认证步骤,不过需要配置额外的AuthenticationManager和UserDetailsServiceImpl,这两个配置只是AuthenticationManager的一种实现,和上面的流程区别不大,目的就是为了拿到用户的信息和权限进行认证import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.security.core.GrantedAuthority; import org.springframework.security.core.authority.SimpleGrantedAuthority; 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.List; import java.util.stream.Collectors;  @Service public class UserDetailsServiceImpl implements UserDetailsService{  	private static final Logger logger = LoggerFactory.getLogger( UserDetailsServiceImpl.class );  	@Autowired 	private UserManager userManager;  	@Autowired 	private RoleManager roleManager;  	@Override 	public UserDetails loadUserByUsername( String username ) throws UsernameNotFoundException{  		User user = userManager.findByName( username ); 		if( user == null ){ 			logger.info( "登录用户[{}]没注册!", username ); 			throw new UsernameNotFoundException( "登录用户[" + username + "]没注册!" ); 		} 		return new org.springframework.security.core.userdetails.User( user.getUsername(), "", getAuthority( username ) ); 	}  	private List<? extends GrantedAuthority> getAuthority( String username ){  		List userRole = userManager.findUserRole( username ); 		List roleIds = userRole.stream().map( Role::getId ).collect( Collectors.toList() ); 		List rolePermission = roleManager.findRolePermission( roleIds ); 		return rolePermission.stream().map( one -> new SimpleGrantedAuthority( one.getName() ) ).collect( Collectors.toList() ); 	} } 	@Override 	@Bean 	public AuthenticationManager authenticationManagerBean() throws Exception{  		DaoAuthenticationProvider daoAuthenticationProvider = new DaoAuthenticationProvider(); 		daoAuthenticationProvider.setUserDetailsService( userDetailsService ); 		daoAuthenticationProvider.setPasswordEncoder( NoOpPasswordEncoder.getInstance() ); 		return new ProviderManager( daoAuthenticationProvider ); 	} 结论
  通过这样的方式,同样实现了权限认证,同时Spring Security会将用户信息和权限缓存到了Session中,这样就不用每次去数据库获取总结
  可以通过两种方式来实现不登录使用SpringSecurity的权限功能手动组装认证过的Authentication直接写到SecurityContext,需要我们自己使用过滤器控制写入和清除手动组装未认证过的Authentication,并交给Spring Security认证,并写入SecurityContext附
  Spring Security是如何配置的,因为只使用权限功能,所有允许所有的路径访问(我们的单点登录会限制接口的访问)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.authentication.ProviderManager; import org.springframework.security.authentication.dao.DaoAuthenticationProvider; import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity; import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; import org.springframework.security.core.userdetails.UserDetailsService; import org.springframework.security.crypto.password.NoOpPasswordEncoder; import org.springframework.web.cors.CorsConfiguration; import org.springframework.web.cors.CorsConfigurationSource; import org.springframework.web.cors.UrlBasedCorsConfigurationSource;  import java.util.Arrays; import java.util.Collections;    @Configuration @EnableWebSecurity @EnableGlobalMethodSecurity(prePostEnabled = true) public class WebSecurityConfig extends WebSecurityConfigurerAdapter{  	@Autowired 	private UserDetailsService userDetailsService;  	@Override 	protected void configure( HttpSecurity http ) throws Exception{  		http 				.cors() 				.and() 				.csrf() 				.disable() 				.sessionManagement() 				.and() 				.authorizeRequests() 				.anyRequest() 				.permitAll() 				.and() 				.exceptionHandling() 				.accessDeniedHandler( new SimpleAccessDeniedHandler() ); 	}   	@Override 	@Bean 	public AuthenticationManager authenticationManagerBean() throws Exception{  		DaoAuthenticationProvider daoAuthenticationProvider = new DaoAuthenticationProvider(); 		daoAuthenticationProvider.setUserDetailsService( userDetailsService ); 		daoAuthenticationProvider.setPasswordEncoder( NoOpPasswordEncoder.getInstance() ); 		return new ProviderManager( daoAuthenticationProvider ); 	}  	@Bean 	public CorsConfigurationSource corsConfigurationSource(){  		CorsConfiguration configuration = new CorsConfiguration(); 		configuration.setAllowedOrigins( Collections.singletonList( "*" ) ); 		configuration.setAllowedMethods( Arrays.asList( "GET", "HEAD", "POST", "PUT", "DELETE", "OPTIONS" ) ); 		configuration.setAllowCredentials( true ); 		configuration.setAllowedHeaders( Collections.singletonList( "*" ) ); 		configuration.setMaxAge( 3600L ); 		UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource(); 		source.registerCorsConfiguration( "/**", configuration ); 		return source; 	}  }

库克良心了,iPhoneSE3至少有4个惊喜,果粉幸福来得太突然据外媒letsgodigital爆料,苹果将于3月8日举行春季新品发布会,届时将会发布万众期待的第三代iPhoneSE新机(也称iPhoneSE3)。据悉,新款iPhoneSE3将开学季专属优惠来了!用华为笔记本平板开启新学期吧随着春天的脚步近了,崭新的学期也在悄然到来。在开学季即将来临之际,不少学子也开始准备起了在学校中所必不可少的高科技装备。对于大部分的大学生而言,如何高效地听课向来是个难题,虽然不少见过大海吗?那就发几张大海的美景照片吧,让大家欣赏欣赏?居住在有海的城市,一年也顶多到海边二三次,避开暑假旺季,都是淡季去玩,人少又安静,可以坐在岩石上,静静的听海浪冲刷拍打岩石的声音,慢慢的欣赏大海的美!这是冬天拍的连云港的海,美不美DDR5内存怎么选?频率下差异大吗?通过测试告诉你随着Intel第12代酷睿处理器的发布,DDR5和PCIe5。0的加持让Intel有了更多战未来的可能。相较于DDR4内存,DDR5内存在频率上直接起飞,默认频率也来到了4800M做ACDC电源时,你们都使用的什么芯片?使用多少频率控制?做ACDC电源时,你们都使用的什么芯片?使用多少频率控制?不通则已,一通则通。现如今的ACDC电源管理芯片种类繁多,要全部搞懂这些电源管理芯片,可以成为高级电子工程师了。前两年的悟NFT市场蓬勃发展,关键在于这五因素NFT是骗局还是值得参与的大事件?它是会像mRNA疫苗那样的突破,还是会像ICO一样腐烂?NFT市场究竟会取代传统市场,还是会像泡沫一样破灭?没有人能给出准确的答案。但我们现在可以李录169亿持仓曝光!清仓拼多多,加仓美国银行和Meta,重仓邮储银行大賺20亿北京时间2月16日,芒格衣钵传人李录旗下的喜马拉雅资本向美国SEC提交了其美股最新持仓情况!截至2021年末,喜马拉雅资本的总持仓规模为26。65亿美元(约合169亿人民币),较三每日晨读智能汽车晨读自动驾驶汽车。Day21什么是自动驾驶汽车?自动驾驶汽车是无人驾驶汽车,不需要人工操作自己可以走的车2自动驾驶汽车有什么特点?只要开启自动驾驶系统就可以走了,因为装有人工智能芯菠萝手机拳打三星脚踢苹果,能跟外星人视频?网友华为也要靠边随着iPhone14规格价格和发布日期等信息曝光,越来越多人加入到苹果新机相关话题讨论中。意外的是,在这些讨论中,出现了一些异常奇葩的声音。就在大家纷纷猜测iPhone14是升级4厉害了,安卓13中可用虚拟机运行Windows11,大神演示玩DOOM现在提起虚拟机安卓模拟器相信大家都已经很熟悉了,但是,大家平时接触的比较多的一般都是在Windows系统内通过虚拟机运行安卓模拟器,在Windows系统中实现对安卓系统的仿真。有没腾讯大手笔!用虚幻引擎升级QQ,竟是为QQ元宇宙开路?近年来不少数据统计显示,刚刚度过23周岁生日的QQ,移动端月活跃用户正在不断下滑,微信突破12亿用户的同时,QQ却已经跌破6亿用户了,虽然横向对比其他社交产品依旧牛逼,但对于它本身
合肥露笑董事长程明公司还没到考虑良率和投资回报率的阶段每经记者朱成祥每经编辑文多2021年,新能源车对碳化硅功率器件的需求,导致导电型碳化硅衬底一片难求。近期,跨界该领域的露笑科技披露,合肥露笑半导体项目一期已完成主要设备的安装调试,西街观察平台互通,私域流量的真正机遇以屏蔽网址链接问题整治为重点方向,分步骤分阶段的解决大平台相互封杀,在监管部门的督促下,互联网拆墙箭在弦上。往大了说,是保护网民用户合法权益的初心,也夹杂着商业公司分果果的竞合博弈传苹果iPhone14在美国将仅支持eSIM,同时取消SIM卡槽对于最近几年刚刚兴起的eSIM,很多网友应该并不陌生,因为已经不少智能手表支持该功能,由于不用装电话卡就可以实现通话和接收信息,所以极大的提高了智能手机的独立性。而在智能手机方面,突发!中国移动发布重要消息,加拿大业务于明年1月5日起停止运营每经编辑杜宇日前,中国移动加拿大子公司CMLink在官网发文称,中国移动加拿大子公司CMLink业务将于2022年1月5日起停止运营。2022年3月31日前您现有的服务将不会受影响社区团购大戏下半场,冷暖谁人知?社区团购大戏进入了下半程,阿里京东拼多多美团等互联网巨头之间的战火日渐平息。一片嘘声中,有些曾经叱咤风云的主角领了盒饭,其他大大小小的角色也走到了命运三岔口。(图Pexels)文欧几个点告诉你,为什么要做小程序微信小程序自发布到现在,入口和功能的迭代速度有目共睹,这也让很多企业和创业者看到了当中蕴藏的商机,也急切的希望能抓住这波红利,为自己的企业谋求更多的发展空间。但是市面上已经发布的小滴滴退市了,中概互联还有救吗?目前市场上对于丐帮的担心主要来源于两个部分1国内反垄断,对于目前业绩和未来预期的影响2中美竞争,对于丐帮的不确定性。首先说第一个,反垄断。打开自家的篱笆,让对手进来的同时,你也可以董明珠钦点22岁梦羽童为直播接班人申请梦羽童商标,她凭什么嗨,大家晚上好,我是买买乐天派,一起来看今天的吧。说起董明珠应该无人不知无人不晓吧。董明珠这个与格力空调画等号的女人,无论做空调,还是卖空调,都推向一种极致状态投入巨资自主研发,自那些年余承东吹过的牛1五年内小米将消失(未实现)2鸿蒙系统比安卓快60(小白评测打开软件速度华为中等)3华为可以做到不用美国元器件,目前少量用是赏他们一口饭吃。(未实现)4用华为一般不用充电宝,带充电新诺基亚7360规格被曝7000mAhLCD直屏,还有骁龙8Gen1移动平台细心的网友会发现,诺基亚手机这几年存在感不高,但它曝光的新机数量却非常高。而近日诺基亚手机又双叒一款新机传来消息,它就是新版诺基亚7360。对于7080后而言,诺基亚7360并不陌每日优鲜高品质多选择的平台时代的发展为人们带去了许多多元化的选择,就拿我们日常生活中吃的食物而言,每日优鲜已经成为生鲜零售知名度最高的买菜优质平台,其旗下的产品十分广泛,不仅可以轻松拿捏住居民的胃,还可以满