iis服务器助手广告广告
返回顶部
首页 > 资讯 > 精选 >Spring Security单点登录的权限功能怎么使用
  • 494
分享到

Spring Security单点登录的权限功能怎么使用

2023-06-29 20:06:15 494人浏览 泡泡鱼
摘要

这篇文章主要介绍“spring Security单点登录的权限功能怎么使用”的相关知识,小编通过实际案例向大家展示操作过程,操作方法简单快捷,实用性强,希望这篇“Spring Security单点登录的权限功能怎么使用”

这篇文章主要介绍“spring Security单点登录的权限功能怎么使用”的相关知识,小编通过实际案例向大家展示操作过程,操作方法简单快捷,实用性强,希望这篇“Spring Security单点登录的权限功能怎么使用”文章能帮助大家解决问题。

背景

在配置中心增加权限功能

  • 目前配置中心已经包含了单点登录功能,可以通过统一页面进行登录,登录完会将用户写入用户表

  • RBAC的用户、角色、权限表CRUD、授权等都已经完成

  • 希望不用用户再次登录,就可以使用SpringSecurity的权限控制

Spring Security

Spring Security最主要的两个功能:认证和授权

功能解决的问题Spring Security中主要类
认证(Authentication)你是谁AuthenticationManager
授权(Authorization)你可以做什么AuthorizationManager

实现

在这先简单了解一下Spring Security的架构是怎样的,如何可以认证和授权的

过滤器大家应该都了解,这属于Servlet的范畴,Servlet 过滤器可以动态地拦截请求和响应,以变换或使用包含在请求或响应中的信息

Spring Security单点登录的权限功能怎么使用

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{@Autowiredprivate SSOUtils ssoUtils;@Autowiredprivate UserManager userManager;@Autowiredprivate RoleManager roleManager;@Overridepublic void init( FilterConfig filterConfig ) throws ServletException{}@Overridepublic void doFilter( ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain )throws IOException, ServletException{setAuthentication(servletRequest);filterChain.doFilter( servletRequest, servletResponse );clearAuthentication();}@Overridepublic void destroy(){}private void setAuthentication( ServletRequest request ){Map<String, String> 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<Role> userRole = userManager.findUserRole( username );List<Long> roleIds = userRole.stream().map( Role::getId ).collect( Collectors.toList() );List<Permission> rolePermission = roleManager.findRolePermission( roleIds );List<SimpleGrantedAuthority> 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;@Servicepublic class UserDetailsServiceImpl implements UserDetailsService{private static final Logger logger = LoggerFactory.getLogger( UserDetailsServiceImpl.class );@Autowiredprivate UserManager userManager;@Autowiredprivate RoleManager roleManager;@Overridepublic 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<Role> userRole = userManager.findUserRole( username );List<Long> roleIds = userRole.stream().map( Role::getId ).collect( Collectors.toList() );List<Permission> rolePermission = roleManager.findRolePermission( roleIds );return rolePermission.stream().map( one -> new SimpleGrantedAuthority( one.getName() ) ).collect( Collectors.toList() );}}
@Override@Beanpublic 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{@Autowiredprivate UserDetailsService userDetailsService;@Overrideprotected void configure( HttpSecurity http ) throws Exception{http.cors().and().csrf().disable().sessionManagement().and().authorizeRequests().anyRequest().permitAll().and().exceptionHandling().accessDeniedHandler( new SimpleAccessDeniedHandler() );}@Override@Beanpublic AuthenticationManager authenticationManagerBean() throws Exception{DaoAuthenticationProvider daoAuthenticationProvider = new DaoAuthenticationProvider();daoAuthenticationProvider.setUserDetailsService( userDetailsService );daoAuthenticationProvider.setPasswordEncoder( NoOpPasswordEncoder.getInstance() );return new ProviderManager( daoAuthenticationProvider );}@Beanpublic 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;}}

关于“Spring Security单点登录的权限功能怎么使用”的内容就介绍到这里了,感谢大家的阅读。如果想了解更多行业相关的知识,可以关注编程网精选频道,小编每天都会为大家更新不同的知识点。

--结束END--

本文标题: Spring Security单点登录的权限功能怎么使用

本文链接: https://www.lsjlt.com/news/326305.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • Spring Security单点登录的权限功能怎么使用
    这篇文章主要介绍“Spring Security单点登录的权限功能怎么使用”的相关知识,小编通过实际案例向大家展示操作过程,操作方法简单快捷,实用性强,希望这篇“Spring Security单点登录的权限功能怎么使用”...
    99+
    2023-06-29
  • Spring boot security权限管理集成cas单点登录功能的实现
    目录1.Spring boot集成Spring security2.部署CAS server3.配置CAS client挣扎了两周,Spring security的cas终于搞出来了...
    99+
    2022-11-13
  • SpringSecurity使用单点登录的权限功能
    目录背景Spring Security实现已经有了单点登录页面,Spring Security怎么登录,不登录可以拿到权限吗Authentication继续分析结论如何手动登录Spr...
    99+
    2022-11-13
  • 一个注解搞定Spring Security基于Oauth2的SSO单点登录功能
    目录一、说明二、原理说明2.1. 同域单点登录2.2. 跨域单点登录2.3. 基于Oauth2的跨域单点登录流程三、Spring Security实现四、demo下载地址 一、说明 ...
    99+
    2022-11-12
  • 怎么使用Spring MVC拦截器实现一个登录功能
    怎么使用Spring MVC拦截器实现一个登录功能?相信很多没有经验的人对此束手无策,为此本文总结了问题出现的原因和解决方法,通过这篇文章希望你能解决这个问题。HandlerInterceptor接口Spring MVC中的Intercep...
    99+
    2023-05-31
    springmvc
  • 怎么使用ThinkPHP实现用户权限的功能
    这篇“怎么使用ThinkPHP实现用户权限的功能”文章的知识点大部分人都不太理解,所以小编给大家总结了以下内容,内容详细,步骤清晰,具有一定的借鉴价值,希望大家阅读完这篇文章能有所收获,下面我们一起来看看这篇“怎么使用ThinkPHP实现用...
    99+
    2023-07-05
  • 腾讯云服务器怎么使用登录密码设置的权限
    腾讯云服务器是一个安全的服务器,允许用户登录到服务器并设置他们的登录密码。为了确保用户的安全,您需要提供用户的登录密码才能使用腾讯云服务器。以下是一个可能的步骤: 在用户登录之前,您需要提供用户名和密码。您可以通过用户名和密码来访问腾讯...
    99+
    2023-10-26
    腾讯 权限 密码
  • 腾讯云服务器怎么使用登录密码设置的权限呢
    如果您的腾讯云服务器需要进行登录密码设置,可以使用以下步骤进行操作: 将登录密码存储在本地计算机上。这将在您访问时提供保护,以免他人获取您的登录信息。 在计算机上登录腾讯云服务器,点击控制台菜单。 使用您的账户或密码登录。使用默认密码或...
    99+
    2023-10-27
    腾讯 权限 密码
  • 腾讯云服务器怎么使用登录密码设置的权限管理
    腾讯云服务器通常都提供登录密码设置的权限管理功能,以下是具体步骤: 在电脑上打开控制台,输入管理员密码进入系统界面。 进入系统界面后,在权限管理处可以看到登录密码设置的选项,可以根据自己的需求设置登录密码的权限。 点击相应的选项进行设置...
    99+
    2023-10-27
    腾讯 权限 密码
  • 腾讯云服务器怎么使用登录账号的功能
    腾讯云服务器使用登录账号的功能需要以下步骤: 打开腾讯云服务器软件,进入到登录页面。 输入账号登录信息,包括账号密码、验证码和手机号码等,确保信息准确无误。 登录账号后,点击左侧的“更多功能”选项,进入到其他选项页面。 在其他选项页面中...
    99+
    2023-10-26
    腾讯 账号 功能
  • 腾讯云服务器怎么使用登录账号的功能呢
    如果您已经拥有腾讯云服务器,以下是使用登录账号功能的步骤: 创建一个新账号:登录到腾讯云服务器上的用户账户界面,在该界面上点击“创建新账号”。 输入账号密码:在登录界面上输入您的账号密码,这是登录腾讯云服务器的必备步骤。 创建密码管理器...
    99+
    2023-10-26
    腾讯 账号 功能
  • 腾讯云服务器怎么使用登录密码设置的权限呢苹果手机
    首先,在使用腾讯云服务器时,用户需要创建一个登录账户,这个账户必须是独立的。用户需要使用自己的用户名和密码来登录账户,这个密码应该是固定的,不能随意更改。同时,用户还需要创建一个管理员账户,管理员账户可以管理其服务器,包括创建数据库、创建应...
    99+
    2023-10-28
    腾讯 权限 苹果
  • Java怎么使用ThreadLocal实现当前登录信息的存取功能
    本篇内容主要讲解“Java怎么使用ThreadLocal实现当前登录信息的存取功能”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“Java怎么使用ThreadLocal实现当前登录信息的存取功能”...
    99+
    2023-07-05
  • 腾讯云服务器怎么使用登录账号的功能呢苹果
    如果您想使用腾讯云服务器上的账号登录功能,您可以按照以下步骤操作: 打开腾讯云应用程序。 登录腾讯云服务器。 选择您的云服务器或主机。 输入您的云服务器账户和密码。 点击“登录”按钮进入账户登录页面。 请注意,登录过程中,需要您输入您...
    99+
    2023-10-27
    腾讯 账号 苹果
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作