java spring security oauth2 动态 修改当前登录用户的 角色以及权限(无需重新登录)

请结合2.0查看解决了当前问题
如何修改其他用户权限
修改用户信息没有效果等


    private final CacheManager cacheManager;
    private final RedisConnectionFactory redisConnectionFactory;
    private final AuthenticationKeyGenerator authenticationKeyGenerator = new
            DefaultAuthenticationKeyGenerator();
    private final JdkSerializationStrategy serializationStrategy = new JdkSerializationStrategy();
    
/**
	 * 动态修改自身权限,无需重新登录
	 * @return
	 */
	@PostMapping("/oneselfUpdateAuth")
	public R oneselfUpdateAuth() {
       //获取当前用户信息
		BaseUser users = SecurityUtils.getUser();

		//token存放的地方
		RedisTokenStore tokenStore = new RedisTokenStore(redisConnectionFactory);
		//设置前缀 base_oauth:
		tokenStore.setPrefix(SecurityConstants.BASE_PREFIX + SecurityConstants.OAUTH_PREFIX);
		tokenStore.setAuthenticationKeyGenerator(new DefaultAuthenticationKeyGenerator() {
			@Override
			public String extractKey(OAuth2Authentication authentication) {
				return super.extractKey(authentication) + ":" + TenantContextHolder.getTenantId();
			}
		});
		//根据id获取用户信息
		UserVO user = sysUserService.selectUserVoById(users.getId());
		//获取当前用户的认证信息
		Authentication authentication=SecurityContextHolder.getContext().getAuthentication();

		//添加权限的地方随便测试一下
		Set<GrantedAuthority> dbAuthsSet = new HashSet<>(authentication.getAuthorities());
		//增加一个权限
		dbAuthsSet.add(new SimpleGrantedAuthority("salaryother:warningteam:testroleid"));

		Collection<? extends GrantedAuthority> authorities =dbAuthsSet;



//				AuthorityUtils
//				.createAuthorityList(dbAuthsSet.toArray(new String[0]));

		//监测当前用户是否锁定
		boolean enabled = StrUtil.equals(user.getLockFlag(), CommonConstants.STATUS_NORMAL);
		// 构造security用户,SecurityConstants.BCRYPT为加密特征码
		BaseUser itduUser = new BaseUser(user.getId(), user.getOrganId(), user.getTenantId(), user.getUsername(), SecurityConstants.BCRYPT + user.getPassword(), enabled,
				true, true, CommonConstants.STATUS_NORMAL.equals(user.getLockFlag()), authorities);
		//从缓存中获取用户信息 String USER_CACHE = "user_cache";
		Cache cache = cacheManager.getCache(CacheConstants.USER_CACHE);
		if (cache != null) {
			//存入缓存
			cache.put(user.getUsername(), itduUser);
		}
		if (authentication instanceof OAuth2Authentication) {
			OAuth2Authentication originalOAuth2Authentication = (OAuth2Authentication) authentication;
			if (!originalOAuth2Authentication.isClientOnly()) {
				Authentication userAuthentication = originalOAuth2Authentication.getUserAuthentication();
				if (userAuthentication instanceof UsernamePasswordAuthenticationToken) {
					//替换用户信息
					UsernamePasswordAuthenticationToken usernamePasswordAuthentication = new UsernamePasswordAuthenticationToken(itduUser, "N_A", authorities);
					usernamePasswordAuthentication.setDetails(itduUser);
					OAuth2Authentication oauth2Authentication = new OAuth2Authentication(originalOAuth2Authentication.getOAuth2Request(), usernamePasswordAuthentication);
					oauth2Authentication.setDetails(itduUser);
					//提取秘钥
					String key = authenticationKeyGenerator.extractKey(originalOAuth2Authentication);
					//这里获取auth_to_access不知道长可以去redis看 本项目用的是 base_oauth:auth_to_access:key:tenantId 每个项目用的可能不一样
					byte[] serializedKey =  serializationStrategy.serialize(SecurityConstants.BASE_PREFIX + SecurityConstants.OAUTH_PREFIX+ "auth_to_access:"+ key+":"+user.getTenantId());
					byte[] bytes = null;
					RedisConnection conn = redisConnectionFactory.getConnection();
					try {
						bytes = conn.get(serializedKey);
					} finally {
						conn.close();
					}
					//获取到token
					OAuth2AccessToken accessToken =serializationStrategy.deserialize(bytes,OAuth2AccessToken.class);
					
					//更新这个token权限
					tokenStore.storeAccessToken(accessToken,oauth2Authentication);
				}
			}
		}


		return R.ok();
	}

测试一下

 @RequestMapping(value="/testRoleId")
    @PreAuthorize("@ato.hasAuthority('salaryother:warningteam:testroleid')")
    public R testRoleId()  {
     return R.ok("通过权限校验");
    }

定义一个没有当前权限的用户登录获取token进行测试
在这里插入图片描述

调用权限更新接口

在这里插入图片描述
重新调用接口测试权限
在这里插入图片描述

ok,权限已经修改完毕,重新刷新token的话权限还是存在,这个就不测了,当然如果重新登录的话,权限一样会被更新,之后失效要想永久修改那就得修改数据库

  • 1
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 7
    评论
好的,下面分别给出基于 Spring SecurityOAuth2 的用户鉴权、权限限制 Demo。 1. Spring Security Demo 首先,创建一个基于 Spring Boot 的 Maven 项目,并添加 Spring Security 依赖: ```xml <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-security</artifactId> </dependency> </dependencies> ``` 接着,在 `application.yml` 中配置用户信息: ```yml spring: security: user: name: admin password: 123456 roles: ADMIN ``` 其中,`name` 和 `password` 分别表示用户名和密码,`roles` 表示用户角色。 然后,创建一个 Spring Security 的配置类: ```java @Configuration @EnableWebSecurity public class SecurityConfig extends WebSecurityConfigurerAdapter { @Override protected void configure(HttpSecurity http) throws Exception { http.authorizeRequests() .antMatchers("/admin/**").hasRole("ADMIN") // ADMIN 角色才能访问 /admin/** .anyRequest().authenticated() // 其他请求需要认证 .and().formLogin().permitAll(); // 开启表单登录 } @Override protected void configure(AuthenticationManagerBuilder auth) throws Exception { auth.inMemoryAuthentication() // 在内存中配置用户信息 .withUser("admin").password("{noop}123456").roles("ADMIN"); // ADMIN 角色用户 } } ``` 其中,`configure(HttpSecurity http)` 方法用于配置请求的安全策略,`configure(AuthenticationManagerBuilder auth)` 方法用于配置用户信息。在这里,我们将 ADMIN 角色用户赋予访问 `/admin/**` 的权限。 最后,创建一个简单的控制器: ```java @RestController public class DemoController { @GetMapping("/") public String home() { return "Hello, world!"; } @GetMapping("/admin") public String admin() { return "Hello, admin!"; } } ``` 在这个控制器中,我们定义了两个请求,`/` 和 `/admin`,其中 `/` 是公共资源,任何人都可以访问,而 `/admin` 是受保护的资源,只有 ADMIN 角色用户才能访问。 2. OAuth2 Demo 首先,创建一个基于 Spring Boot 的 Maven 项目,并添加 OAuth2 依赖: ```xml <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-oauth2-client</artifactId> </dependency> </dependencies> ``` 接着,在 `application.yml` 中配置 OAuth2 客户端信息: ```yml spring: security: oauth2: client: registration: google: client-id: {your-client-id} client-secret: {your-client-secret} scope: - email - profile ``` 其中,`client-id` 和 `client-secret` 分别表示 OAuth2 客户端的 ID 和密钥,`scope` 表示访问权限。 然后,创建一个 OAuth2 认证服务器: ```java @Configuration @EnableAuthorizationServer public class AuthServerConfig extends AuthorizationServerConfigurerAdapter { @Autowired private AuthenticationManager authenticationManager; @Override public void configure(ClientDetailsServiceConfigurer clients) throws Exception { clients.inMemory() // 在内存中配置客户端信息 .withClient("client") // 客户端 ID .secret("{noop}secret") // 客户端密钥 .authorizedGrantTypes("authorization_code", "refresh_token") // 授权类型 .scopes("read", "write") // 访问权限 .redirectUris("http://localhost:8080/login/oauth2/code/google"); // 回调地址 } @Override public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception { endpoints.authenticationManager(authenticationManager); // 配置认证管理器 } } ``` 其中,`configure(ClientDetailsServiceConfigurer clients)` 方法用于配置客户端信息,`configure(AuthorizationServerEndpointsConfigurer endpoints)` 方法用于配置认证管理器。在这里,我们将使用 `inMemory` 方式配置客户端信息,并且支持 `authorization_code` 和 `refresh_token` 授权类型。 接着,创建一个 OAuth2 资源服务器: ```java @Configuration @EnableResourceServer public class ResourceServerConfig extends ResourceServerConfigurerAdapter { @Override public void configure(HttpSecurity http) throws Exception { http.authorizeRequests() .antMatchers("/api/**").authenticated() // 需要认证才能访问 /api/** .anyRequest().permitAll(); // 其他请求允许访问 } } ``` 其中,`configure(HttpSecurity http)` 方法用于配置请求的安全策略。在这里,我们将 `/api/**` 定义为受保护的资源,只有认证后的用户才能访问。 最后,创建一个简单的控制器: ```java @RestController public class DemoController { @GetMapping("/") public String home() { return "Hello, world!"; } @GetMapping("/api") public String api() { return "Hello, OAuth2!"; } } ``` 在这个控制器中,我们定义了两个请求,`/` 和 `/api`,其中 `/` 是公共资源,任何人都可以访问,而 `/api` 是受保护的资源,只有认证后的用户才能访问。 以上就是基于 Spring SecurityOAuth2 的用户鉴权、权限限制 Demo。希望对你有所帮助!
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值