博客
关于我
Spring Security OAuth2--密码模式 实战
阅读量:106 次
发布时间:2019-02-25

本文共 9450 字,大约阅读时间需要 31 分钟。

OAuth2协议与Spring Boot密码模式认证服务器搭建

OAuth2协议简介

OAuth2是一种广泛用于授权管理的协议,主要用于规范令牌的发放过程。其最新版本为2.0,与之前的1.0不兼容,主要提供了四种授权模式:授权码模式、简化模式、密码模式和客户端模式。本文将重点介绍密码模式,因为前端系统采用用户名密码登录。

密码模式认证流程

在密码模式中,用户向客户端提供用户名和密码,客户端通过认证服务器获取令牌。整个流程分为三个步骤:

  • 用户访问客户端:用户通过客户端提交包含用户名和密码的请求,请求目标资源的访问令牌。
  • 认证服务器验证身份:认证服务器接收请求,验证用户的用户名和密码信息。
  • 返回访问令牌:认证通过后,认证服务器返回access_token给客户端。
  • 系统搭建

    项目依赖管理

    我们需要一个完整的Spring Boot项目架构,以下是项目的POM文件配置:

    4.0.0
    org.springframework.boot
    spring-boot-starter-parent
    2.1.6.RELEASE
    demo
    security
    0.0.1-SNAPSHOT
    security
    Spring Boot Security Demo Project
    1.8
    Greenwich.SR1
    org.springframework.boot
    spring-boot-starter-web
    org.springframework.cloud
    spring-cloud-starter-oauth2
    org.springframework.cloud
    spring-cloud-starter-security
    org.apache.commons
    commons-lang3
    org.springframework.boot
    spring-boot-starter-data-redis
    io.jsonwebtoken
    jjwt
    0.9.1
    org.springframework.cloud
    spring-cloud-dependencies
    ${spring-cloud.version}
    pom
    import
    org.springframework.boot
    spring-boot-maven-plugin

    Redis配置

    为了存储认证信息,我们选择Redis作为token存储。以下是Redis配置文件示例:

    spring:    redis:        host: 127.0.0.1        port: 6379        password: KCl9HfqbVnhQ5c3n        database: 0

    安全配置类

    定义一个安全配置类SecurityConfig,用于管理用户认证:

    package com.example.demo.security.config;import com.example.demo.security.service.UserDetailService;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.context.annotation.Bean;import org.springframework.core.annotation.Order;import org.springframework.security.authentication.AuthenticationManager;import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;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.crypto.bcrypt.BCryptPasswordEncoder;import org.springframework.security.crypto.password.PasswordEncoder;@EnableWebSecurity@Order(2)public class SecurityConfig extends WebSecurityConfigurerAdapter {    @Autowired    private UserDetailService userDetailService;    @Bean    public PasswordEncoder passwordEncoder() {        return new BCryptPasswordEncoder();    }    @Bean    @Override    public AuthenticationManager authenticationManagerBean() throws Exception {        return super.authenticationManagerBean();    }    @Override    protected void configure(HttpSecurity http) throws Exception {        http.requestMatchers().antMatchers("/oauth/**")                .and()                .authorizeRequests()                .antMatchers("/oauth/**").authenticated()                .and()                .csrf().disable();    }    @Override    protected void configure(AuthenticationManagerBuilder auth) throws Exception {        auth.userDetailsService(userDetailService).passwordEncoder(passwordEncoder());    }}

    资源服务器配置

    定义一个资源服务器配置类ResourceServerConfig,用于管理资源访问权限:

    package com.example.demo.security.config;import org.springframework.context.annotation.Configuration;import org.springframework.security.config.annotation.web.builders.HttpSecurity;import org.springframework.security.oauth2.config.annotation.web.configuration.EnableResourceServer;import org.springframework.security.oauth2.config.annotation.web.configuration.ResourceServerConfigurerAdapter;@Configuration@EnableResourceServerpublic class ResourceServerConfig extends ResourceServerConfigurerAdapter {    @Override    public void configure(HttpSecurity http) throws Exception {        http.csrf().disable()                .requestMatchers().antMatchers("/**")                .and()                .authorizeRequests()                .antMatchers("/**").authenticated();    }}

    认证服务器配置

    定义一个认证服务器配置类AuthorizationServerConfig,用于管理令牌颁发:

    package com.example.demo.security.config;import com.example.demo.security.service.UserDetailService;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.Configuration;import org.springframework.context.annotation.Primary;import org.springframework.data.redis.connection.RedisConnectionFactory;import org.springframework.security.authentication.AuthenticationManager;import org.springframework.security.crypto.password.PasswordEncoder;import org.springframework.security.oauth2.config.annotation.configuers.ClientDetailsServiceConfigurer;import org.springframework.security.oauth2.config.annotation.web.configuration.AuthorizationServerConfigurerAdapter;import org.springframework.security.oauth2.config.annotation.web.configuers.AuthorizationServerEndpointsConfigurer;import org.springframework.security.oauth2.provider.token.DefaultTokenServices;import org.springframework.security.oauth2.provider.token.TokenStore;import org.springframework.security.oauth2.provider.token.store.redis.RedisTokenStore;@Configuration@EnableAuthorizationServerpublic class AuthorizationServerConfig extends AuthorizationServerConfigurerAdapter {    @Autowired    private AuthenticationManager authenticationManager;    @Autowired    private RedisConnectionFactory redisConnectionFactory;    @Autowired    private UserDetailService userDetailService;    @Autowired    private PasswordEncoder passwordEncoder;    @Override    public void configure(ClientDetailsServiceConfigurer clients) throws Exception {        clients.inMemory()                .withClient("auth")                .secret(passwordEncoder.encode("123456"))                .authorizedGrantTypes("password", "refresh_token")                .scopes("all");    }    @Override    public void configure(AuthorizationServerEndpointsConfigurer endpoints) {        endpoints.tokenStore(tokenStore())                .userDetailsService(userDetailService)                .authenticationManager(authenticationManager)                .tokenServices(defaultTokenServices());    }    @Bean    public TokenStore tokenStore() {        return new RedisTokenStore(redisConnectionFactory);    }    @Primary    @Bean    public DefaultTokenServices defaultTokenServices() {        DefaultTokenServices tokenServices = new DefaultTokenServices();        tokenServices.setTokenStore(tokenStore());        tokenServices.setSupportRefreshToken(true);        tokenServices.setAccessTokenValiditySeconds(60 * 60 * 24);        tokenServices.setRefreshTokenValiditySeconds(60 * 60 * 24 * 7);        return tokenServices;    }}

    用户DetailsService

    定义一个用户DetailsService类UserDetailService,用于用户认证:

    package com.example.demo.security.service;import com.example.demo.security.entity.AuthUser;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.security.core.authority.AuthorityUtils;import org.springframework.security.core.userdetails.User;import org.springframework.security.core.userdetails.UserDetails;import org.springframework.security.core.userdetails.UserDetailsService;import org.springframework.security.crypto.password.PasswordEncoder;import org.springframework.stereotype.Service;@Servicepublic class UserDetailService implements UserDetailsService {    @Autowired    private PasswordEncoder passwordEncoder;    @Override    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {        AuthUser user = new AuthUser();        user.setUsername(username);        user.setPassword(passwordEncoder.encode("123456"));        return new User(username, user.getPassword(), user.isEnabled(),                user.isAccountNonExpired(), user.isCredentialsNonExpired(),                user.isAccountNonLocked(), AuthorityUtils.commaSeparatedStringToAuthorityList("user:add"));    }}

    测试与验证

    通过Postman测试可以验证系统的各个功能:

  • 发送POST请求获取令牌:

    • URL: http://localhost:8081/oauth/token
    • 请求头:Basic base64(client_id:client_secret)
    • 参数:grant_type=password&username=admin&password=123456
  • 发送GET请求获取资源:

    • URL: http://localhost:8081/oauth/test
    • 请求头:Authorization: Bearer access_token
  • 发送DELETE请求注销令牌:

    • URL: http://localhost:8081/loginOut
    • 请求头:Authorization: Bearer access_token
  • 发送POST请求刷新令牌:

    • URL: http://localhost:8081/oauth/token
    • 请求头:Authorization: Bearer refresh_token
    • 参数:grant_type=refresh_token
  • 通过以上步骤,可以验证系统的完整认证流程是否正常工作。

    转载地址:http://ms.baihongyu.com/

    你可能感兴趣的文章
    Openlayers高级交互(3/20):动态添加 layer 到 layerGroup,并动态删除
    查看>>
    Openlayers高级交互(4/20):手绘多边形,导出KML文件,可以自定义name和style
    查看>>
    Openlayers高级交互(5/20):右键点击,获取该点下多个图层的feature信息
    查看>>
    Openlayers高级交互(6/20):绘制某点,判断它是否在一个电子围栏内
    查看>>
    Openlayers高级交互(7/20):点击某点弹出窗口,自动播放视频
    查看>>
    Openlayers高级交互(8/20):选取feature,平移feature
    查看>>
    Openlayers高级交互(9/20):编辑图形(放缩、平移、变形、旋转),停止编辑
    查看>>
    Openlayers:DMS-DD坐标形式互相转换
    查看>>
    openlayers:圆孔相机根据卫星经度、纬度、高度、半径比例推算绘制地面的拍摄的区域
    查看>>
    OpenLDAP(2.4.3x)服务器搭建及配置说明
    查看>>
    OpenLDAP编译安装及配置
    查看>>
    Openmax IL (二)Android多媒体编解码Component
    查看>>
    OpenMCU(一):STM32F407 FreeRTOS移植
    查看>>
    OpenMCU(三):STM32F103 FreeRTOS移植
    查看>>
    OpenMCU(三):STM32F103 FreeRTOS移植
    查看>>
    OpenMCU(二):GD32E23xx FreeRTOS移植
    查看>>
    OpenMCU(五):STM32F103时钟树初始化分析
    查看>>
    OpenMCU(四):STM32F103启动汇编代码分析
    查看>>
    OpenMetadata 命令执行漏洞复现(CVE-2024-28255)
    查看>>
    OpenMMLab | AI玩家已上线!和InternLM解锁“谁是卧底”新玩法
    查看>>