在Spring Boot+Spring Security框架里配置UserDetailsService

公司工作需要使用自建的云平台,虽然我是嵌入式工程师但是因为人手不足(主要还是建站的人走了,没人会Java)所以交由我来维护。

这次有了新需求,需要进行权限的分类和管理,由于原先的代码已经经了好几手了(心累啊!!),我需要保持原先的结构不动的情况下加入这些功能,那么原先的方式已经不满足需求了。

查阅了资料以后,决定直接使用UserDetailsService的形式对原先页面进行改造。

我们原先的spring-security.xml有如下代码:

<authentication-manager erase-credentials="false">
        <authentication-provider>
            <jdbc-user-service 
                data-source-ref="dataSource"
                users-by-username-query="select username,password,1 as enabled from sys_user where username=?"
                authorities-by-username-query="select u.username, r.name as role from sys_user u,sys_role_user ur, sys_role r where u.id=ur.Sys_User_id and r.id = ur.Sys_Role_id and u.username= ? "
             />  
       </authentication-provider>
 </authentication-manager>

这里的authentication-provider是使用了直接使用jdbc对数据库进行读取,但是在商业项目中我们不能将数据库结构直接暴露,所以我们要采用UserDetailsService的形式对于用户数据进行管理,同时也方便后期对于权限等地方的操作。

我们这里使用自定义的UserDetailsService来代替原先对数据库的直接操作:

<authentication-manager erase-credentials="false">
    <authentication-provider user-service-ref="myUserDetailsService">
    </authentication-provider>
</authentication-manager>

然后我们在后端,对myUserDetailsService这个类需要进行具体的设计,但是在此之前,我们需要自定义好UserDetails。

package com.hzmsc.scada.entity;

import java.util.Collection;

import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;

public class User implements UserDetails{
   
/**   
 * @title: User
 * @author: zza
 * @date: 2020/3/9 17:05
 * @description: User用于权限验证和获取个人信息等方面,要注意和Users类的区别
*/
    private int id;
    private String username;
    private String password;
    private boolean enabled;
    private Collection<? extends GrantedAuthority> authorities;

    public
  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是使用 Spring Boot + Spring Security 实现多租户的 Java 代码示例: 1. 自定义 UserDetails 类,实现 UserDetails 接口。 ```java public class CustomUserDetails implements UserDetails { private String username; private String password; private List<GrantedAuthority> authorities; private String tenantId; // 省略构造函数和 getter/setter 方法 @Override public Collection<? extends GrantedAuthority> getAuthorities() { return authorities; } @Override public String getPassword() { return password; } @Override public String getUsername() { return username; } @Override public boolean isAccountNonExpired() { return true; } @Override public boolean isAccountNonLocked() { return true; } @Override public boolean isCredentialsNonExpired() { return true; } @Override public boolean isEnabled() { return true; } public String getTenantId() { return tenantId; } public void setTenantId(String tenantId) { this.tenantId = tenantId; } } ``` 2. 自定义 UserDetailsService,从不同的数据源中加载用户信息。 ```java @Service public class CustomUserDetailsService implements UserDetailsService { @Autowired private UserRepository userRepository; @Override public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException { User user = userRepository.findByUsername(username); if (user == null) { throw new UsernameNotFoundException("User not found"); } CustomUserDetails userDetails = new CustomUserDetails(); userDetails.setUsername(user.getUsername()); userDetails.setPassword(user.getPassword()); userDetails.setTenantId(user.getTenantId()); List<GrantedAuthority> authorities = new ArrayList<>(); for (Role role : user.getRoles()) { authorities.add(new SimpleGrantedAuthority(role.getName())); } userDetails.setAuthorities(authorities); return userDetails; } } ``` 3. 自定义 Filter,在请求进入应用程序之前,从请求中获取租户信息,并将其存储在 ThreadLocal 中。 ```java public class TenantFilter extends OncePerRequestFilter { private static final String TENANT_HEADER = "X-TenantID"; @Override protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException { String tenantId = request.getHeader(TENANT_HEADER); if (StringUtils.isEmpty(tenantId)) { throw new ServletException("Missing X-TenantID header"); } TenantContext.setCurrentTenant(tenantId); filterChain.doFilter(request, response); } } ``` 4. 自定义 TenantContext,将当前租户信息存储在 ThreadLocal 中。 ```java public class TenantContext { private static final ThreadLocal<String> currentTenant = new ThreadLocal<>(); public static void setCurrentTenant(String tenantId) { currentTenant.set(tenantId); } public static String getCurrentTenant() { return currentTenant.get(); } public static void clear() { currentTenant.remove(); } } ``` 5. 自定义 AuthenticationProvider,从当前租户的数据源中加载用户信息。 ```java public class CustomAuthenticationProvider implements AuthenticationProvider { @Autowired private UserDetailsService userDetailsService; @Override public Authentication authenticate(Authentication authentication) throws AuthenticationException { String username = authentication.getName(); String password = authentication.getCredentials().toString(); CustomUserDetails userDetails = (CustomUserDetails) userDetailsService.loadUserByUsername(username); if (!password.equals(userDetails.getPassword())) { throw new BadCredentialsException("Bad credentials"); } TenantContext.setCurrentTenant(userDetails.getTenantId()); return new UsernamePasswordAuthenticationToken(userDetails, password, userDetails.getAuthorities()); } @Override public boolean supports(Class<?> authentication) { return authentication.equals(UsernamePasswordAuthenticationToken.class); } } ``` 6. 在 WebSecurityConfigurerAdapter 中配置多租户的认证和授权。 ```java @Configuration @EnableWebSecurity public class SecurityConfig extends WebSecurityConfigurerAdapter { @Autowired private CustomAuthenticationProvider authenticationProvider; @Autowired private CustomUserDetailsService userDetailsService; @Override protected void configure(AuthenticationManagerBuilder auth) throws Exception { auth.authenticationProvider(authenticationProvider); auth.userDetailsService(userDetailsService); } @Override protected void configure(HttpSecurity http) throws Exception { http .csrf().disable() .authorizeRequests() .antMatchers("/public/**").permitAll() .antMatchers("/private/**").authenticated() .and() .formLogin() .loginPage("/login") .defaultSuccessUrl("/private/dashboard") .and() .logout() .logoutUrl("/logout") .logoutSuccessUrl("/login") .and() .addFilterBefore(new TenantFilter(), UsernamePasswordAuthenticationFilter.class); } } ``` 以上是使用 Spring Boot + Spring Security 实现多租户的 Java 代码示例,其中 CustomUserDetails、CustomUserDetailsService、CustomAuthenticationProvider 和 TenantContext 都需要根据具体业务场景进行定制。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值