You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Grails 4.x中GraphQL集成Spring Security及视图角色控制实现

Hey there! Let's tackle your two questions about Spring Security integration with Grails 4.x GraphQL, using your provided Career entity as a reference.

1. Implementing Spring Security in Grails 4.x GraphQL

First, make sure you have the core dependencies set up in your build.gradle:

dependencies {
    // Spring Security Core plugin for Grails 4.x
    implementation 'org.grails.plugins:spring-security-core:4.0.0'
    // Grails GraphQL plugin
    implementation 'org.grails.plugins:graphql:1.0.0' // Match version to your Grails 4.x setup
}

Next, configure basic Spring Security rules in grails-app/conf/application.yml to secure the GraphQL endpoint:

grails:
    plugin:
        springsecurity:
            userLookup:
                userDomainClassName: 'com.yourpackage.User' # Update to your User domain
                authorityJoinClassName: 'com.yourpackage.UserRole' # Update to your join class
            authority:
                className: 'com.yourpackage.Role' # Update to your Role domain
            controllerAnnotations:
                staticRules:
                    - pattern: '/graphql'
                      access: ['isAuthenticated()'] # Require login for all GraphQL requests

Now, add role-based checks directly to your GraphQL data fetchers. Let's modify your Career entity example to restrict the careerByName query to users with the ROLE_ADMIN role:

import org.springframework.security.core.context.SecurityContextHolder
import org.springframework.security.access.AccessDeniedException

class Career {
    String name
    String description
    Integer positions

    static graphql = GraphQLMapping.build {
        query('careerByName', Career){
            dataFetcher(new DataFetcher() {
                @Override
                Object get(DataFetchingEnvironment environment) throws Exception {
                    // Get current authenticated user's roles
                    def auth = SecurityContextHolder.context.authentication
                    boolean hasAdminAccess = auth.authorities.any { it.authority == 'ROLE_ADMIN' }

                    if (!hasAdminAccess) {
                        throw new AccessDeniedException("You need admin privileges to access this query")
                    }

                    return Career.findByName(environment.getArgument('name'))
                }
            })
        }
    }

    static constraints = { }
    static mapping = { }
}

If you prefer using Spring Security annotations, create a Spring-managed data fetcher service and annotate the method:

// grails-app/services/CareerDataFetcherService.groovy
import org.springframework.security.access.prepost.PreAuthorize
import org.springframework.stereotype.Service
import graphql.schema.DataFetcher
import graphql.schema.DataFetchingEnvironment

@Service
class CareerDataFetcherService implements DataFetcher<Career> {

    @PreAuthorize("hasRole('ROLE_ADMIN')")
    @Override
    Career get(DataFetchingEnvironment environment) throws Exception {
        return Career.findByName(environment.getArgument('name'))
    }
}

// Update Career.groovy to use the service
static graphql = GraphQLMapping.build {
    query('careerByName', Career) {
        dataFetcher(applicationContext.getBean(CareerDataFetcherService))
    }
}
2. Role-Based Control in Grails GraphQL Views (Field/Query Visibility)

Field-Level Access Control

If you want to restrict access to specific fields (e.g., only admins can see the positions field), add role checks directly in the field's data fetcher:

static graphql = GraphQLMapping.build {
    query('careerByName', Career){
        dataFetcher(...) // Your existing query-level role check

        // Restrict positions field to admins only
        field('positions') {
            dataFetcher(new DataFetcher<Integer>() {
                @Override
                Integer get(DataFetchingEnvironment environment) throws Exception {
                    def auth = SecurityContextHolder.context.authentication
                    if (!auth.authorities.any { it.authority == 'ROLE_ADMIN' }) {
                        return null // Or throw an AccessDeniedException
                    }
                    return environment.source.positions
                }
            })
        }
    }
}

Conditional Query/Field Visibility

To hide entire queries or fields from unauthorised users (so they don't appear in the GraphQL schema), you can conditionally define them based on the user's role:

static graphql = GraphQLMapping.build {
    def auth = SecurityContextHolder.context.authentication
    boolean isAdmin = auth?.authorities?.any { it.authority == 'ROLE_ADMIN' }

    // Only expose the careerByName query to admins
    if (isAdmin) {
        query('careerByName', Career){
            dataFetcher(...)
        }
    }
}

Note: This checks roles at schema build time, so it works best for static role-based visibility. For per-request dynamic checks, stick to data fetcher-level validation.

内容的提问来源于stack exchange,提问作者user2253081

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.08 15:12:51