Java 正在使用Azure目录进行身份验证,并从数据库中获取有效的用户角色

Java 正在使用Azure目录进行身份验证,并从数据库中获取有效的用户角色,java,spring-boot,authentication,spring-security,azure-active-directory,Java,Spring Boot,Authentication,Spring Security,Azure Active Directory,我必须为一个组织设计一个应用程序,在这个组织中,需要使用SSO和使用spring boot的Azure目录进行身份验证 所有员工信息都存储在广告中。我的自定义应用程序将拥有自己的用户及其角色,并保存在数据库中。并非组织中的每位员工都有权访问此应用程序。管理员将在数据库(Mysql)中添加用户及其角色 通过在属性文件中添加相关细节并配置WebSecurity配置类,我能够找到使用AD进行SSO的方法 @EnableWebSecurity @EnableGlobalMethodSecurity(pr

我必须为一个组织设计一个应用程序,在这个组织中,需要使用SSO和使用spring boot的Azure目录进行身份验证

所有员工信息都存储在广告中。我的自定义应用程序将拥有自己的用户及其角色,并保存在数据库中。并非组织中的每位员工都有权访问此应用程序。管理员将在数据库(Mysql)中添加用户及其角色

通过在属性文件中添加相关细节并配置WebSecurity配置类,我能够找到使用AD进行SSO的方法

@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
   @Autowired
   private OAuth2UserService<OidcUserRequest, OidcUser> oidcUserService;

   @Autowired
   private AADAuthenticationFilter aadAuthFilter;


   @Override
   protected void configure(HttpSecurity http) throws Exception {
    http.csrf().disable()
            .authorizeRequests().antMatchers(HttpMethod.OPTIONS, 
             "/**").permitAll().anyRequest().authenticated()
            .and()
            .oauth2Login()
            .userInfoEndpoint()
            .oidcUserService(oidcUserService);

    http
            .addFilterBefore(aadAuthFilter, UsernamePasswordAuthenticationFilter.class);

    http
            .headers()
            .frameOptions().sameOrigin()
            .cacheControl();

       http
              .csrf().disable()
              .authorizeRequests().antMatchers(HttpMethod.OPTIONS, 
              "/**").permitAll().anyRequest().authenticated()
     }

 }
@EnableWebSecurity
@EnableGlobalMethodSecurity(Prespenabled=true)
公共类WebSecurityConfig扩展了WebSecurityConfigureAdapter{
@自动连线
专用OAuth2UserService oidcUserService;
@自动连线
专用AADAuthenticationFilter aadAuthFilter;
@凌驾
受保护的无效配置(HttpSecurity http)引发异常{
http.csrf().disable()
.authorizeRequests().antMatchers(HttpMethod.OPTIONS,
“/**”).permitAll().anyRequest().authenticated()
.及()
.oauth2Login()
.userInfoEndpoint()
.oidcUserService(OIDCUSERVICE);
http
.addFilterBefore(aadAuthFilter,UsernamePasswordAuthenticationFilter.class);
http
.headers()
.frameOptions().sameOrigin()
.cacheControl();
http
.csrf().disable()
.authorizeRequests().antMatchers(HttpMethod.OPTIONS,
“/**”).permitAll().anyRequest().authenticated()
}
}
一旦用户被验证,作为响应,我将获得JWT令牌,我将使用它来处理所有进一步的API请求。但问题是,这里我允许所有员工访问该应用程序,因为他使用AD进行了身份验证。但是,一旦用户通过身份验证,我想检查该用户在数据库中是否可用,如果他不可用,我需要向我的应用程序发送无效用户,如果他是有效用户,我需要获取角色并将其作为有效响应发送到前端

我还想为用户进行服务级别授权,我的大多数服务都使用了@PreAuthorize注释。 @预授权(“hasRole('ROLE\u VIEWER')或hasRole('ROLE\u EDITOR'))

编辑1

public class UserDetailsServiceImpl extends OidcUserService implements 
CustomUserDetailsService {
@Override
public OidcUser loadUser(OidcUserRequest userRequest) throws 
OAuth2AuthenticationException {

    OidcUser oidcUser;

    String mail=userRequest.getClientRegistration().getRegistrationId();

     Set<GrantedAuthority> grantedAuthorities = getAuthorities(mail);

    oidcUser = new DefaultOidcUser(grantedAuthorities, 
    userRequest.getIdToken());

    return oidcUser;


}

private Set<GrantedAuthority> getAuthorities(String email) {
      List<RoleIdDetails> 
     roleIdDetails=usersRepository.getRoleIdDeatils(email);
       final Set<GrantedAuthority> authorities = 
    roleIdDetails.stream().map(role -> new SimpleGrantedAuthority("ROLE_" + 
  role.getRoleName().toString().toUpperCase())).collect(Collectors.toSet());
    return authorities;
   }
 } 
public类UserDetailsServiceImpl扩展了OidcUserService实现
CustomUserDetailsService{
@凌驾
公共OidcUser加载用户(OidcUserRequest userRequest)抛出
OAuth2AuthenticationException{
OidcUser OidcUser;
String mail=userRequest.getClientRegistration().getRegistrationId();
Set grantedAuthories=getAuthories(邮件);
oidcUser=新的默认oidcUser(授权机构,
userRequest.getIdToken());
回归方程;
}
私人设置权限(字符串电子邮件){
列表
roleIdDetails=usersRepository.getRoleIDeatils(电子邮件);
最终设定权限=
roleIdDetails.stream().map(角色->新建SimpleGrantedAuthority(“角色”+
role.getRoleName().toString().toUpperCase()).collect(collector.toSet());
返回当局;
}
} 

我已经用自己的自定义OidcUserService进行了更新,但仍然无法设置角色。

根据我的理解,您不需要使用Mysql数据库来存储用户及其角色,我们可以通过Azure Active Directory来实现这一要求

首先,我们可以在Azure Active Directory中创建一个组,方法是单击Azure门户上的“组”-->“新建组”按钮,然后从Azure广告中的员工中选择要加入此组的成员(如下屏幕截图所示):

然后单击“应用程序注册”并单击“清单”按钮,转到azure广告中的应用程序。

您还可以在上面的屏幕截图中的“Approvles”属性下添加更多角色

之后,在azure ad中的应用程序中,请单击“本地目录中的托管应用程序”。

然后单击“用户和组”-->“添加用户”。

选择我们刚才创建的组并为其选择角色。

现在,您可以通过问题中提到的注释(@PreAuthorize)为用户进行服务级别授权,您也可以参考此注释


顺便说一句,如果我们想在azure ad中为组分配角色,我们需要为azure ad()制定Premium P1或P2计划。如果您没有Premium计划,您可以在最后一个屏幕截图中为每个用户分配一个角色,而不是一个组。

我们也做了类似的事情,在广告验证期间,我们保存来自广告服务的用户名,然后签入数据库。您是否可以在“aadAuthFilter”中添加相同的签入。你能得到用户名吗???@AmanGarg你能告诉我一个资源(或)提供一个如何做到这一点的工作示例吗。谢谢。一种方法可以是在
oidcUserService
方法中的
public OidcUser loadUser(OidcUserRequest userRequest)抛出OAuth2AuthenticationException
OidcUser
实现
DefaultOAuth2User
类。调用
getName
方法获取用户名,然后在loadUser方法本身的数据库中检查user,Ref:@AmanGarg我已经用自定义OidcUserService更新了,但仍然没有用。更新最新代码见编辑1谢谢@Hury Shen,是的,广告提供了添加角色的方法。但在我的场景中,所有角色都已在DB中定义。管理员可以使用我的自定义应用程序向用户添加角色。所以我需要获取这些角色并加载用户