Использование Azure настраиваемых ролей AD Premium с безопасностью Spring для доступа на основе ролей - PullRequest
0 голосов
/ 12 июля 2020

Я создал демонстрационное приложение для загрузки Spring, в котором я хочу использовать аутентификацию и авторизацию AD с использованием AD и безопасности Spring. Посмотрев на Azure документы, я сделал следующее

package com.myapp.contactdb.contactfinder;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;

@RequestMapping("/directory")
public interface Directory {
    @Autowired
    @PreAuthorize("hasRole('Users')")
    @GetMapping("/contact/{mobile}")
    public String getContact(@PathVariable("mobile") Long mobile);
    
    @Autowired
    
    @GetMapping("/contact/data")
    public String getData();

}

, который является остальным API входная точка. Я создал группы и пользователей в нем в соответствующем Azure AD и использовал эту группу, как указано в azure документах, подобных этой

package com.myapp.contactdb;

import org.springframework.beans.factory.annotation.Autowired;
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.config.http.SessionCreationPolicy;
import org.springframework.security.oauth2.client.oidc.userinfo.OidcUserRequest;
import org.springframework.security.oauth2.client.userinfo.OAuth2UserService;
import org.springframework.security.oauth2.core.oidc.user.OidcUser;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;

import com.microsoft.azure.spring.autoconfigure.aad.AADAppRoleStatelessAuthenticationFilter;

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

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
            .authorizeRequests()
            .anyRequest().authenticated()
            .and()
            .oauth2Login()
            .userInfoEndpoint()
            .oidcUserService(oidcUserService);
    }
    
}

, и свойствам приложения как

spring.main.banner-mode=off

# create and drop tables and sequences, loads import.sql
#spring.jpa.hibernate.ddl-auto=create-drop

# MySql settings
spring.datasource.url=jdbc:mysql://localhost:3306/xxxx
spring.datasource.username=root
spring.datasource.password=root
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.jpa.hibernate.naming.physical-strategy=org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl
spring.jpa.properties.hibernate.dialect = org.hibernate.dialect.MySQL8Dialect

# HikariCP settings
# spring.datasource.hikari.*

spring.datasource.hikari.connection-timeout=60000
spring.datasource.hikari.maximum-pool-size=5

# azure.activedirectory.tenant-id
azure.activedirectory.tenant-id = xxxx
azure.activedirectory.client-id = xxxx


# spring.security.oauth2.client.registration.azure.client-id
spring.security.oauth2.client.registration.azure.client-id = xxxxxxx

# spring.security.oauth2.client.registration.azure.client-secret
spring.security.oauth2.client.registration.azure.client-secret = xxxxxxxx

azure.activedirectory.active-directory-groups =  Users

Однако мне нужно авторизоваться с использованием настраиваемых ролей. Я добавил бесплатную пробную версию azure AD и создал роль, а именно «Оператор». Однако проблема в том, какое свойство я использую, чтобы отобразить это в файле app.props, и как заставить роль отражаться в @Preauthorize (hasRole ('Operator')). Есть идеи или что-то, чего я, возможно, не видел?

Ответы [ 2 ]

0 голосов
/ 20 июля 2020

@ Jim,

Итак, наконец, я пошел с этим, изменив класс WebSecurityConfig из приведенного выше вопроса

package com.xxx.contactdb;

import java.util.HashSet;
import java.util.Map;
import java.util.Set;

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.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.oauth2.client.oidc.userinfo.OidcUserRequest;
import org.springframework.security.oauth2.client.oidc.userinfo.OidcUserService;
import org.springframework.security.oauth2.client.userinfo.OAuth2UserService;
import org.springframework.security.oauth2.core.oidc.user.DefaultOidcUser;
import org.springframework.security.oauth2.core.oidc.user.OidcUser;
import org.springframework.security.oauth2.core.oidc.user.OidcUserAuthority;

import net.minidev.json.JSONArray;

@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests().anyRequest().authenticated().and().oauth2Login().userInfoEndpoint()
                .oidcUserService(this.oidcUserService());
    }

    /**
     * Replaces the granted authorities value received in token with the roles value
     * in token received from the app roles attribute defined in manifest and
     * creates a new OIDCUser with updated mappedAuthorities
     * 
     * @return oidcUser
     */
    private OAuth2UserService<OidcUserRequest, OidcUser> oidcUserService() {
        final OidcUserService delegate = new OidcUserService();

        return (userRequest) -> {
            Set<GrantedAuthority> mappedAuthorities = new HashSet<>();
            // Delegate to the default implementation for loading a user
            OidcUser oidcUser = delegate.loadUser(userRequest);
            oidcUser.getAuthorities().forEach(authority -> {
                if (OidcUserAuthority.class.isInstance(authority)) {
                    OidcUserAuthority oidcUserAuthority = (OidcUserAuthority) authority;
                    Map<String, Object> userInfo = oidcUserAuthority.getAttributes();
                    JSONArray roles = null;
                    if (userInfo.containsKey("roles")) {
                        try {
                            roles = (JSONArray) userInfo.get("roles");
                            roles.forEach(s -> {
                                mappedAuthorities.add(new SimpleGrantedAuthority("ROLE_" + (String) s));
                            });
                        } catch (Exception e) {
                            // Replace this with logger during implementation
                            e.printStackTrace();
                        }
                    }
                }
            });
            oidcUser = new DefaultOidcUser(mappedAuthorities, oidcUser.getIdToken(), oidcUser.getUserInfo());

            return oidcUser;
        };
    }

}

Я сделал это изменение для весенней загрузки версии 2.3.1 Release, которая использует Azure 2.3.1 и Spring версию безопасности 5.3.3. Мысль об этом, потому что для загрузки Spring версии 2.1.13 мы могли бы использовать UserAuthoritiesMapping, поскольку у властей было бы сопоставление типов OIDCUserService, которого нет в последней версии. Однако, если кто-то использует DB для заполнения ролей для уполномоченных органов, они все равно могут go с этой опцией, а не опцией OidcUser. Это работает на данный момент.

0 голосов
/ 14 июля 2020

Если вы хотите спроецировать свое приложение с ролью приложения, выполните следующие действия.

В примере используется аутентификация роли приложения для проекта веб-API

  1. Зарегистрируйте приложение веб-API и настройте область действия API.

  2. Определите роль приложения в вашем Azure приложении веб-API API. Добавьте в манифест приложения следующее содержимое:

  "appRoles": [
    {
      "allowedMemberTypes": [
        "User"
      ],
      "displayName": "Admin",
      "id": "2fa848d0-8054-4e11-8c73-7af5f1171001",
      "isEnabled": true,
      "description": "Full admin access",
      "value": "Admin"
    },
    {
      "allowedMemberTypes": [
        "User"
      ],
      "displayName": "User",
      "id": "f8ed78b5-fabc-488e-968b-baa48a570001",
      "isEnabled": true,
      "description": "Normal user access",
      "value": "User"
    }
  ],

Назначьте эти роли пользователю

Зарегистрируйте клиентское приложение в Azure AD и настройте разрешения API

Включить неявный поток в клиентском приложении

Настроить приложение API

a. SDK

  <dependency>
            <groupId>com.microsoft.azure</groupId>
            <artifactId>azure-active-directory-spring-boot-starter</artifactId>
           <version>2.3.1</version>
        </dependency>

б. application.properties

azure.activedirectory.session-stateless=true
azure.activedirectory.client-id=xxxxxx-your-client-id-xxxxxx
azure.activedirectory.appIdUri=xxxxxx-your-appIDUri-xxxxxx

c. Класс WebSecurityConfig

@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {

    @Autowired
    private AADAppRoleStatelessAuthenticationFilter aadAuthFilter;

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.csrf().disable();

        http.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.NEVER);

        http.authorizeRequests()
            .antMatchers("/", "/index.html", "/public").permitAll()
            .anyRequest().authenticated();

        http.addFilterBefore(aadAuthFilter, UsernamePasswordAuthenticationFilter.class);

    }
}

d. Контроллер

@RestController
public class HelloController {

    @GetMapping("/public")
    @ResponseBody
    public String publicMethod() {
        return "public endpoint response";
    }

    @GetMapping("/authorized")
    @ResponseBody
    @PreAuthorize("hasAnyRole('User','Admin')")
    public String onlyAuthorizedUsers() {

        return "authorized endpoint response";
    }

    @GetMapping("/admin/demo")
    @PreAuthorize("hasRole('Admin')")
    @ResponseBody
    public String onlyForAdmins() {
        return "admin endpoint";
    }
}
Тест. Я использую одну страницу для тестирования

enter image description here enter image description here

For more details, please refer to здесь и здесь

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...