Реализация режима клиента и режима пароля Spring Boot Security Oauth2

Spring Boot

Пример основного содержания

  • 1. Режим множественной аутентификации (режим пароля, режим клиента)
  • 2. Токен хранится в поддержке Redis
  • 3. Защита ресурсов
  • 4. Пользователи режима пароля и разрешения хранятся в базе данных
  • 5. Инструкция по применению

Пример кода — гитхаб

вводить

режим клиента учетных данных клиента oauth2 для получения процесса access_token

Режим клиента (предоставление учетных данных клиента) означает, что клиент аутентифицируется у «поставщика услуг» от своего имени, а не от имени пользователя. Строго говоря, клиентский режим не является частью проблемы, которую призван решить фреймворк OAuth. В этом режиме пользователь регистрируется напрямую у клиента, а клиент запрашивает у «поставщика услуг» предоставление услуг от своего имени, по сути проблемы с авторизацией не возникает.

  • (A) Клиент аутентифицируется на сервере аутентификации и запрашивает токен доступа. HTTP-запрос, отправленный клиентом, содержит следующие параметры: GrantType: указывает тип авторизации, значение здесь фиксируется как «clientcredentials», обязательный параметр. область: указывает область разрешения, необязательно.

  • (B) После того, как сервер аутентификации подтвердит правильность, он предоставляет токен доступа клиенту.

режим пароля oauth2 для получения процесса access_token

В режиме пароля (предоставление учетных данных владельца ресурса) пользователь предоставляет клиенту свое имя пользователя и пароль. Клиент использует эту информацию для запроса авторизации у «поставщика услуг». В этом режиме пользователь должен сообщить свой пароль клиенту, но клиент не должен хранить пароль. Это обычно используется, когда пользователь имеет высокое доверие к клиенту, например, клиент является частью операционной системы или производится известной компанией. Сервер аутентификации должен использовать этот режим только в том случае, если другие режимы авторизации не могут быть реализованы.

  • (A) Пользователь предоставляет клиенту имя пользователя и пароль.

  • (B) Клиент отправляет имя пользователя и пароль на сервер аутентификации и запрашивает токен у последнего. HTTP-запрос, отправленный клиентом, содержит следующие параметры: grant_type: Указывает тип авторизации.Значение здесь фиксировано на «пароль», что является обязательным. имя пользователя: Указывает имя пользователя, обязательное. пароль: указывает пароль пользователя, обязательный. область: указывает область разрешения, необязательно.

  • (C) После того, как сервер аутентификации подтвердит правильность, он предоставляет токен доступа клиенту.

Конечные точки по умолчанию, предоставляемые Oauth2 (конечные точки)

  • /oauth/authorize: конечная точка авторизации
  • /oauth/token: конечная точка токена
  • /oauth/confirm_access: пользователь подтверждает авторизацию для отправки конечной точки
  • /oauth/error: конечная точка сообщения об ошибке службы авторизации
  • /oauth/check_token: конечная точка разрешения токена для доступа к службе ресурсов.
  • /oauth/token_key: конечная точка для предоставления открытого ключа при использовании токена JWT.

Введение в пример использования

1. Получить access_token в терминальном режиме

http://localhost:8080/oauth/token?grant_type=client_credentials&scope=select&client_id=client_1&client_secret=123456

вернуть результат

{
    "access_token": "67a2c8f6-bd08-4409-a0d6-6ba61a4be950",
    "token_type": "bearer",
    "expires_in": 41203,
    "scope": "select"
}

2. Получить access_token в режиме пароля

http://localhost:8080/oauth/token?username=user&password=123456&grant_type=password&scope=select&client_id=client_2&client_secret=123456

вернуть результат

{
    "access_token": "b3d2c131-1225-45b4-9ff5-51ec17511cee",
    "token_type": "bearer",
    "refresh_token": "8495d597-0560-4598-95ef-143c0855363c",
    "expires_in": 42417,
    "scope": "select"
}

3. Обновить access_token

http://localhost:8080/oauth/token?grant_type=refresh_token&refresh_token=8495d597-0560-4598-95ef-143c0855363c&client_id=client_2&client_secret=123456

вернуть результат

{
    "access_token": "63de6c71-672f-418c-80eb-0c9abc95b67c",
    "token_type": "bearer",
    "refresh_token": "8495d597-0560-4598-95ef-143c0855363c",
    "expires_in": 43199,
    "scope": "select"
}

4. Доступ к защищенным ресурсам

http://localhost:8080/order/1?access_token=b3d2c131-1225-45b4-9ff5-51ec17511cee

правильно вернуть данные

Процесс кода весенней безопасности oauth2

3 основных класса конфигурации, интегрированные безопасностью oauth2

  • 1. Конфигурация службы ресурсов ResourceServerConfiguration
  • 2. Конфигурация службы аутентификации авторизации AuthorizationServerConfiguration
  • 3.конфигурация безопасности

1.pom.xml добавить зависимости maven

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-security</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.security.oauth</groupId>
            <artifactId>spring-security-oauth2</artifactId>
            <version>2.3.6.RELEASE</version>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-redis</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-thymeleaf</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>

        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>8.0.17</version>
        </dependency>

        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-boot-starter</artifactId>
            <version>3.1.2</version>
        </dependency>

        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>

        <dependency>
            <groupId>cn.hutool</groupId>
            <artifactId>hutool-all</artifactId>
            <version>4.6.1</version>
            <scope>test</scope>
        </dependency>
    </dependencies>

В основном используются: безопасность, oauth2, redis, mysql, mybatis-plus и другие компоненты.

2. Конфигурация аутентификации и авторизации AuthorizationServerConfigurerAdapter.java

@Configuration
@EnableAuthorizationServer
public class AuthorizationServerConfig extends AuthorizationServerConfigurerAdapter {

    private static final String RESOURCE_IDS = "order";

    @Autowired
    AuthenticationManager authenticationManager;

    @Autowired
    RedisConnectionFactory redisConnectionFactory;

    @Autowired
    private UserDetailsService userDetailsService;

    @Override
    public void configure(ClientDetailsServiceConfigurer clients) throws Exception {

        String finalSecret = "{bcrypt}" + new BCryptPasswordEncoder().encode("123456");
        //配置两个客户端,一个用于password认证一个用于client认证
        clients.inMemory()

                //client模式
                .withClient("client_1")
                .resourceIds(RESOURCE_IDS)
                .authorizedGrantTypes("client_credentials", "refresh_token")
                .scopes("select")
                .authorities("oauth2")
                .secret(finalSecret)

                .and()

                //密码模式
                .withClient("client_2")
                .resourceIds(RESOURCE_IDS)
                .authorizedGrantTypes("password", "refresh_token")
                .scopes("select")
                .authorities("oauth2")
                .secret(finalSecret);
    }

    /**
     * 认证服务端点配置
     */
    @Override
    public void configure(AuthorizationServerEndpointsConfigurer endpoints) {
        endpoints
                //用户管理
                .userDetailsService(userDetailsService)
                //token存到redis
                .tokenStore(new RedisTokenStore(redisConnectionFactory))
                //启用oauth2管理
                .authenticationManager(authenticationManager)
                //接收GET和POST
                .allowedTokenEndpointRequestMethods(HttpMethod.GET, HttpMethod.POST);
    }

    @Override
    public void configure(AuthorizationServerSecurityConfigurer oauthServer) {
        oauthServer.allowFormAuthenticationForClients();
    }
}

3. Конфигурация ресурса ResourceServerConfig.java

@Configuration
@EnableResourceServer
public class ResourceServerConfig extends ResourceServerConfigurerAdapter {

    private static final String RESOURCE_IDS = "order";

    @Override
    public void configure(ResourceServerSecurityConfigurer resources) {
        resources.resourceId(RESOURCE_IDS).stateless(true);
    }

    @Override
    public void configure(HttpSecurity httpSecurity) throws Exception {
        httpSecurity
                .authorizeRequests()
                .antMatchers("/order/**").authenticated();      //配置order访问控制,必须认证过后才可以访问

    }
}

4. Пользователи и разрешения в режиме пароля хранятся в базе данных UserDetailsServiceImpl.java


@Service
public class UserDetailsServiceImpl implements UserDetailsService {

    @Autowired
    private UserServiceImpl userService;

    /**
     * 实现UserDetailsService中的loadUserByUsername方法,用于加载用户数据
     */
    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        User user = userService.queryUserByUsername(username);
        if (user == null) {
            throw new UsernameNotFoundException("用户不存在");
        }

        //用户权限列表
        Collection<? extends GrantedAuthority> authorities = userService.queryUserAuthorities(user.getId());

        return new AuthUser(
                user.getId(),
                user.getUsername(),
                user.getPassword(),
                true,
                true,
                true,
                true,
                authorities);
    }
}

5. Конфигурация WebSecurityConfig

@Configuration
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {

    @Bean
    PasswordEncoder passwordEncoder() {
        return PasswordEncoderFactories.createDelegatingPasswordEncoder();
    }

    /**
     * 注入AuthenticationManager接口,启用OAuth2密码模式
     *
     * @return
     * @throws Exception
     */
    @Bean
    @Override
    public AuthenticationManager authenticationManagerBean() throws Exception {
        AuthenticationManager manager = super.authenticationManagerBean();
        return manager;
    }

    /**
     * 通过HttpSecurity实现Security的自定义过滤配置
     *
     * @param httpSecurity
     * @throws Exception
     */
    @Override
    protected void configure(HttpSecurity httpSecurity) throws Exception {
        httpSecurity
                .requestMatchers().anyRequest()
                .and()
                .authorizeRequests()
                .antMatchers("/oauth/**").permitAll();
    }
}

6.конфигурация application.yml

server:
  port: 8080

spring:
  thymeleaf:
    encoding: UTF-8
    cache: false

  datasource:
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://localhost:3306/easy_web?useSSL=false&serverTimezone=UTC
    username: root
    password: 123456

  redis:
    host: 127.0.0.1
    port: 6379
    password:

logging.level.org.springframework.security: DEBUG

7.inital.sql скрипт инициализации базы данных

DROP TABLE IF EXISTS `user`;
DROP TABLE IF EXISTS `role`;
DROP TABLE IF EXISTS `user_role`;
DROP TABLE IF EXISTS `role_permission`;
DROP TABLE IF EXISTS `permission`;

CREATE TABLE `user` (
`id` bigint(11) NOT NULL AUTO_INCREMENT,
`username` varchar(255) NOT NULL,
`password` varchar(255) NOT NULL,
PRIMARY KEY (`id`) 
);
CREATE TABLE `role` (
`id` bigint(11) NOT NULL AUTO_INCREMENT,
`name` varchar(255) NOT NULL,
PRIMARY KEY (`id`) 
);
CREATE TABLE `user_role` (
`id` bigint(11) NOT NULL AUTO_INCREMENT,
`user_id` bigint(11) NOT NULL,
`role_id` bigint(11) NOT NULL,
PRIMARY KEY (`id`)
);
CREATE TABLE `role_permission` (
`id` bigint(11) NOT NULL AUTO_INCREMENT,
`role_id` bigint(11) NOT NULL,
`permission_id` bigint(11) NOT NULL,
PRIMARY KEY (`id`)
);
CREATE TABLE `permission` (
`id` bigint(11) NOT NULL AUTO_INCREMENT,
`url` varchar(255) NOT NULL,
`name` varchar(255) NOT NULL,
`description` varchar(255) NULL,
`pid` bigint(11) NOT NULL,
PRIMARY KEY (`id`) 
);

INSERT INTO user (id, username, password) VALUES (1,'user','{bcrypt}$2a$10$Tme77eHtXzcB8ghQUepYguJr7P7ESg0Y7XHMnk60s.kf2A.BWBD9m');
INSERT INTO user (id, username , password) VALUES (2,'admin','{bcrypt}$2a$10$Tme77eHtXzcB8ghQUepYguJr7P7ESg0Y7XHMnk60s.kf2A.BWBD9m');
INSERT INTO role (id, name) VALUES (1,'USER');
INSERT INTO role (id, name) VALUES (2,'ADMIN');
INSERT INTO permission (id, url, name, pid) VALUES (1,'/user/common','common',0);
INSERT INTO permission (id, url, name, pid) VALUES (2,'/user/admin','admin',0);
INSERT INTO user_role (user_id, role_id) VALUES (1, 1);
INSERT INTO user_role (user_id, role_id) VALUES (2, 1);
INSERT INTO user_role (user_id, role_id) VALUES (2, 2);
INSERT INTO role_permission (role_id, permission_id) VALUES (1, 1);
INSERT INTO role_permission (role_id, permission_id) VALUES (2, 1);
INSERT INTO role_permission (role_id, permission_id) VALUES (2, 2);

После вышеупомянутых семи шагов мы быстро реализовали функции режима пароля и режима клиента Oauth2.

материал