authorization of mongoDB3.4

本文介绍了如何在MongoDB 3.4中设置授权参数并创建用户,通过修改配置文件实现安全验证,并提供了使用C++驱动进行认证的示例代码。

如果在程序中,要带口令访问mongoDB, 需要设置mongoDB的授权参数,建立用户等操作。
看到人家已经做好了这个实验, 自己也验证了一下。
发现了一个小坑,/etc/mongod.conf中是新语法,是有层级的,下一个层级的内容开始位置不要用\t,而是2个空格才生效。刚装完的mongoDB3.4的mongod.conf中有些例子,才知道要用2个空格代替\t.

虽然旧语法也能用在mongod.conf中,也好使。但是为了避免未知坑,还是用新语法。
要跟着官方文裆,测试用例,示例走,才能少入坑。

实验

设置mongodb3.4的授权

对应的mongo-cxx-driver版本为3.1.1

> use admin
switched to db admin

> db.createUser({ user: "admin", pwd: "adminpassword", roles: [{ role: "userAdminAnyDatabase", db: "admin" }] })
Successfully added user: {
    "user" : "admin",
    "roles" : [
        {
            "role" : "userAdminAnyDatabase",
            "db" : "admin"
        }
    ]
}

> db.auth("admin", "adminpassword")
1

> exit
bye

sudo vi /etc/mongod.conf
add code below after #security:

// authorization前面是2个空格, 不能是\t
#security:
security:
  authorization: enabled

# not below, don't table key, need 2 space
#security:
#   authorization: enabled

sudo service mongod restart
now mongod error, not start
if mongod was run, info below

sudo service mongod status
[ ok ] Checking status of database: mongod running.


sudo service mongod status
[FAIL] Checking status of database: mongod apparently not running failed!

///////////////////////////////////////
back to mongo

> use admin
switched to db admin

> db.auth("admin", "adminpassword")
1

> use test
switched to db test

> db.createUser({ user: "test_usr", pwd: "test_pwd", roles: [{ role: "dbOwner", db: "test" }] })
Successfully added user: {
    "user" : "test_usr",
    "roles" : [
        {
            "role" : "dbOwner",
            "db" : "test"
        }
    ]
}

> db.auth("test_usr", "test_pwd")
1

> show collections
fs.chunks
fs.files

// the author uri is below
mongodb://youruser:yourpassword@localhost/yourdatabase
mongodb://test_usr:test_pwd@localhost/test

写测试程序进行带口令登录验证

只有增删改查时,才会用到用户登录后的权限。
如果不带口令登录,不是一上来就报错,而是要增删改查时,才抛未登录异常。

bool class_mongo_opt::test()
{
    bool b_rc = false;
    std::string errmsg;
    int i_bp_index = 0;

    printf(">> class_mongo_opt::test() v1.0.0.1\n");
    try {
        // https://docs.mongodb.com/master/reference/connection-string/
        // mongodb://192.168.2.60:27017
        // mongodb://test_usr:test_pwd@localhost/test


        // mongocxx::exception& ex = not authorized on test to execute command { aggregate: "restaurants", pipeline: [ { $group: { _id: "$borough", count: { $sum: 1 } } } ], cursor: {} }: generic server error

        printf("bp = %d\n", i_bp_index++);
        mongocxx::instance inst{}; // This should be done only once.
        printf("bp = %d\n", i_bp_index++);

        // 无认证的写法
        mongocxx::client conn{mongocxx::uri{}};

        // 有认证的写法
        /*
        mongocxx::uri uri("mongodb://test_usr:test_pwd@localhost:27017/test");
        mongocxx::client conn(uri);
        */

        printf("bp = %d\n", i_bp_index++);
        auto db = conn["test"];

        // Group documents by field and calculate count.
        {
            // @begin: cpp-group-documents-by-a-field-and-calculate-count
            printf("1 bp = %d\n", i_bp_index++);
            mongocxx::pipeline stages;
            printf("bp = %d\n", i_bp_index++);
            bsoncxx::builder::stream::document group_stage;

            printf("bp = %d\n", i_bp_index++);
            group_stage << "_id"
                        << "$borough"
                        << "count" << open_document << "$sum" << 1 << close_document;

            printf("bp = %d\n", i_bp_index++);
            stages.group(group_stage.view());

            printf("bp = %d\n", i_bp_index++);
            auto cursor = db["restaurants"].aggregate(stages);

            printf("8 bp = %d\n", i_bp_index++);
            // mongocxx::exception& ex = not authorized on test to execute command { aggregate: "restaurants", pipeline: [ { $group: { _id: "$borough", count: { $sum: 1 } } } ], cursor: {} }: generic server error
            // cursor 遍历时,需要登录数据库后才有权限
            for (auto&& doc : cursor) {
                printf("10 bp = %d\n", i_bp_index++);
                std::cout << bsoncxx::to_json(doc) << std::endl;
            }
            // @end: cpp-group-documents-by-a-field-and-calculate-count
        printf("9 bp = %d\n", i_bp_index++);
        }

        // Filter and group documents.
        {
            // @begin: cpp-filter-and-group-documents
            printf("3 bp = %d\n", i_bp_index++);
            mongocxx::pipeline stages;
            printf("bp = %d\n", i_bp_index++);
            bsoncxx::builder::stream::document match_stage, group_stage;

            printf("bp = %d\n", i_bp_index++);
            match_stage << "borough"
                        << "Queens"
                        << "cuisine"
                        << "Brazilian";

            printf("bp = %d\n", i_bp_index++);
            group_stage << "_id"
                        << "$address.zipcode"
                        << "count" << open_document << "$sum" << 1 << close_document;

            printf("bp = %d\n", i_bp_index++);
            stages.match(match_stage.view()).group(group_stage.view());

            printf("bp = %d\n", i_bp_index++);
            auto cursor = db["restaurants"].aggregate(stages);

            printf("bp = %d\n", i_bp_index++);
            for (auto&& doc : cursor) {
                printf("bp = %d\n", i_bp_index++);
                std::cout << bsoncxx::to_json(doc) << std::endl;
            }
            // @end: cpp-filter-and-group-documents
        printf("4 bp = %d\n", i_bp_index++);
        }

        b_rc = true;
    }
    /*
    catch(mongocxx::exception& ex) {
        printf("mongocxx::exception& ex = %s\n", ex.what());
        b_rc = false;
    }
    */

    catch(std::exception& ex) {
        errmsg = ex.what();
        printf("exception : %s\n", errmsg.c_str());
        b_rc = false;       
    }

    catch(...) {
        printf("catch...\n");
        b_rc = false;       
    }
    return b_rc;
}
<think>好的,我现在需要帮助用户解决如何集成Spring Boot Starter OAuth2 Authorization Server 3.4与企业微信实现扫码登录的问题。首先,我需要回忆一下相关的知识,确保自己理解用户的需求和正确的技术路径。 用户提到的是OAuth2 Authorization Server 3.4版本,这应该是Spring Authorization Server项目,因为Spring官方已经不再维护Spring Security OAuth,转而推荐使用Spring Authorization Server。企业微信的扫码登录属于OAuth2的流程,所以需要将Authorization Server配置为企业微信的OAuth2客户端,同时处理回调、用户认证等步骤。 首先,我需要确定所需的依赖项。用户使用的是Spring Boot,所以应该添加Spring Authorization Server和Spring Security相关的starter。另外,可能还需要Spring Web和Thymeleaf(如果前端需要页面的话)。不过企业微信扫码登录通常涉及后端处理回调,所以可能不需要前端模板,但可能需要配置一些端点。 接下来,配置Authorization Server。需要定义RegisteredClientRepository、AuthorizationServerSettings,以及配置SecurityFilterChain来设置OAuth2的相关端点。这里需要注册企业微信作为客户端,填写client-id、client-secret、redirect-uri等。企业微信的OAuth2配置可能需要特定的授权范围和令牌端点,需要查阅企业微信的文档获取正确的URL,比如授权端点和令牌端点的路径。 然后,处理用户认证。用户扫码后,企业微信会回调到我们的redirect-uri,通常需要处理授权码,获取access token,然后获取用户信息。这里可能需要自定义UserDetailsService,将企业微信返回的用户信息转换为系统内的用户凭证。同时,可能需要实现OAuth2UserService来加载用户信息。 另外,需要配置Spring Security的安全策略,允许公开授权端点和回调端点,同时保护其他端点。可能需要自定义登录页面,或者直接重定向到企业微信的扫码页面。 可能遇到的问题包括:配置client-authentication-method为client_secret_post或client_secret_basic,企业微信可能要求特定的认证方式;redirect-uri需要与企业微信后台配置的一致;scope需要正确设置以获取用户信息;还有处理用户信息的方式,可能需要自定义OAuth2UserService来解析企业微信返回的数据。 然后,我需要检查是否遗漏了任何步骤,比如是否需要配置JWT或者Token的生成方式,但用户的问题主要是扫码登录,可能默认使用Opaque Token,或者根据需求配置JWT。不过企业微信的集成可能只需要标准的OAuth2流程,不需要修改Token的生成方式。 最后,需要提供配置示例和依赖说明,确保用户能够按照步骤操作。可能还需要提醒用户替换实际参数,如corp-id、secret、redirect-uri等,并检查企业微信的应用配置是否正确。 总结步骤: 1. 添加依赖:Spring Authorization Server, Spring Security, Spring Web。 2. 配置Authorization Server的RegisteredClient,使用企业微信的客户端信息。 3. 配置SecurityFilterChain,设置OAuth2端点和安全规则。 4. 实现UserDetailsService,可能关联本地用户数据。 5. 处理回调,获取用户信息,可能需要自定义OAuth2UserService。 6. 测试整个流程,确保扫码登录成功。 现在需要将这些步骤整理成结构化的回答,包含配置代码示例和依赖说明,同时确保引用正确的引用来源,比如引用[1]和[2]中提到的UserDetailsService的配置,可能需要结合到回答中。</think>### 分步实现企业微信扫码登录集成 #### 1. 添加依赖 ```xml <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-security</artifactId> </dependency> <dependency> <groupId>org.springframework.security</groupId> <artifactId>spring-security-oauth2-authorization-server</artifactId> <version>3.4.0</version> </dependency> ``` #### 2. 配置企业微信客户端信息 ```java @Bean public RegisteredClientRepository registeredClientRepository() { RegisteredClient qywxClient = RegisteredClient.withId("qywx") .clientId("企业微信CORP_ID") .clientSecret("{noop}企业微信SECRET") .clientAuthenticationMethod(ClientAuthenticationMethod.CLIENT_SECRET_BASIC) .authorizationGrantType(AuthorizationGrantType.AUTHORIZATION_CODE) .redirectUri("https://your-domain.com/login/oauth2/code/qywx") .scope(new OAuth2Scope("snsapi_login")) .clientSettings(ClientSettings.builder() .requireAuthorizationConsent(false) .build()) .build(); return new InMemoryRegisteredClientRepository(qywxClient); } ``` #### 3. 配置Authorization Server端点 ```java @Bean @Order(1) public SecurityFilterChain authorizationServerSecurityFilterChain(HttpSecurity http) throws Exception { OAuth2AuthorizationServerConfiguration.applyDefaultSecurity(http); http.getConfigurer(OAuth2AuthorizationServerConfigurer.class) .oidc(Customizer.withDefaults()); http.exceptionHandling(exceptions -> exceptions.authenticationEntryPoint(new LoginUrlAuthenticationEntryPoint("/login")) ); return http.build(); } @Bean public AuthorizationServerSettings authorizationServerSettings() { return AuthorizationServerSettings.builder() .issuer("https://your-domain.com") .build(); } ``` #### 4. 实现用户关联逻辑(需自定义) ```java @Component public class QywxOAuth2UserService implements OAuth2UserService<OAuth2UserRequest, OAuth2User> { @Override public OAuth2User loadUser(OAuth2UserRequest request) throws OAuth2AuthenticationException { // 调用企业微信API获取用户信息 String userInfoUrl = "https://qyapi.weixin.qq.com/cgi-bin/user/getuserinfo?access_token=" + request.getAccessToken().getTokenValue(); // 解析用户信息并关联本地账户 // 返回包含权限信息的UserDetails对象 return new DefaultOAuth2User(...); } } ``` #### 5. 配置安全策略 ```java @Bean @Order(2) public SecurityFilterChain defaultSecurityFilterChain(HttpSecurity http) throws Exception { http .authorizeHttpRequests(authorize -> authorize .requestMatchers("/login/**").permitAll() .anyRequest().authenticated() ) .oauth2Login(oauth2 -> oauth2 .userInfoEndpoint(userInfo -> userInfo .userService(qywxOAuth2UserService) ) ); return http.build(); } ``` ### 企业微信端配置要点 1. 登录企业微信后台 > 应用管理 > 创建扫码登录应用 2. 设置授权回调域为`your-domain.com` 3. 获取`CORP_ID`和`SECRET`填入客户端配置 ### 测试流程 1. 访问`/oauth2/authorize?response_type=code&client_id=CORP_ID&scope=snsapi_login` 2. 重定向到企业微信扫码页面 3. 扫码成功后回调到配置的redirect_uri 4. 系统自动完成用户关联与登录[^2]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值