Spring Security OAuth2 Demo —— 密码模式(Password)

前情回顾

前几节分享了OAuth2的流程与授权码模式和隐式授权模式两种的Demo,我们了解到授权码模式是OAuth2四种模式流程最复杂模式,复杂程度由大至小:授权码模式 > 隐式授权模式 > 密码模式 > 客户端模式

其中密码模式的流程是:让用户填写表单提交到授权服务器,表单中包含用户的用户名、密码、客户端的id和密钥的加密串,授权服务器先解析并校验客户端信息,然后校验用户信息,完全通过返回access_token,否则默认都是401 http状态码,提示未授权无法访问

本文目标

编写与说明密码模式的Spring Security Oauth2的demo实现,让未了解过相关知识的读者对此授权流程有个更直观的概念

以下分成授权服务器与资源服务器分别进行解释,只讲关键部分,详情见Github:https://github.com/hellxz/spring-security-oauth2-learn

搭建密码模式授权服务器

代码结构与之前两个模式相同,这里便不再进行说明

SecurityConfig配置

package com.github.hellxz.oauth2.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
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.core.userdetails.UsernameNotFoundException;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.util.StringUtils;

import java.util.ArrayList;
import java.util.Collections;

@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Bean
    public PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }

    @Bean
    public AuthenticationManager authenticationManager() throws Exception {
        return super.authenticationManager();
    }

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.inMemoryAuthentication()
                .withUser("hellxz")
                .password(passwordEncoder().encode("xyz"))
                .authorities(new ArrayList<>(0));
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        //所有请求必须认证
        http.authorizeRequests().anyRequest().authenticated();
    }
}

基本的SpringSecurity的配置,开启Spring Security的Web安全功能,填了一个用户信息,所有资源必须经过授权才可以访问

AuthorizationConfig授权服务器配置

package com.github.hellxz.oauth2.config;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.oauth2.config.annotation.configurers.ClientDetailsServiceConfigurer;
import org.springframework.security.oauth2.config.annotation.web.configuration.AuthorizationServerConfigurerAdapter;
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableAuthorizationServer;
import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerEndpointsConfigurer;
import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerSecurityConfigurer;

@Configuration
@EnableAuthorizationServer
public class AuthorizationConfig extends AuthorizationServerConfigurerAdapter {

    @Autowired
    private AuthenticationManager authenticationManager;//密码模式需要注入认证管理器

    @Autowired
    public PasswordEncoder passwordEncoder;

    //配置客户端
    @Override
    public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
        //@formatter:off
        clients.inMemory()
                .withClient("client-a")
                  .secret(passwordEncoder.encode("client-a-secret"))
                  .authorizedGrantTypes("password") //主要是这里,开始了密码模式
                  .scopes("read_scope");
        //@formatter:on
    }

    @Override
    public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
        endpoints.authenticationManager(authenticationManager);//密码模式必须添加authenticationManager
    }

    @Override
    public void configure(AuthorizationServerSecurityConfigurer security) throws Exception {
        security.allowFormAuthenticationForClients()
                .checkTokenAccess("isAuthenticated()");
    }
}

这里开启了授权服务器的功能,与上几篇文章中不同的是注入了AuthenticationManager,以及在configure(AuthorizationServerEndpointsConfigurer endpoints)方法中设置了AuthenticationManager

application.properties配置sever.port=8080

搭建资源服务器

这里的关键就是ResourceConfig,配置比较简单与其它几个模式完全一致,模式的不同主要表现在授权服务器与客户端服务器上,资源服务器只做token的校验与给予资源

package com.github.hellxz.oauth2.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableResourceServer;
import org.springframework.security.oauth2.config.annotation.web.configuration.ResourceServerConfigurerAdapter;
import org.springframework.security.oauth2.config.annotation.web.configurers.ResourceServerSecurityConfigurer;
import org.springframework.security.oauth2.provider.token.RemoteTokenServices;

@Configuration
@EnableResourceServer
public class ResourceConfig extends ResourceServerConfigurerAdapter {

    @Bean
    public PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }

    @Primary
    @Bean
    public RemoteTokenServices remoteTokenServices() {
        final RemoteTokenServices tokenServices = new RemoteTokenServices();
        //设置授权服务器check_token端点完整地址
        tokenServices.setCheckTokenEndpointUrl("http://localhost:8080/oauth/check_token");
        //设置客户端id与secret,注意:client_secret值不能使用passwordEncoder加密!
        tokenServices.setClientId("client-a");
        tokenServices.setClientSecret("client-a-secret");
        return tokenServices;
    }

    @Override
    public void configure(HttpSecurity http) throws Exception {
        //设置创建session策略
        http.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.IF_REQUIRED);
        //@formatter:off
        //所有请求必须授权
        http.authorizeRequests()
                .anyRequest().authenticated();
        //@formatter:on
    }

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

ResourceController主要接收一个用户名,返回一个username与email的json串

application.properties设置server.port=8081

准备工作到这里就差不多了,开始测试

测试流程

这里客户端使用postman手动发送请求进行演示

  • 访问/oauth/token端点,获取token

    http://localhost:8080/oauth/token?username=hellxz&password=xyz&scope=read_scope&grant_type=password

    请求头:

    请求体:

  • token返回值
    {
        "access_token": "4a3c351d-770d-42aa-af39-3f54b50152e9",
        "token_type": "bearer",
        "expires_in": 43199,
        "scope": "read_scope"
    }
  • 使用token调用资源,访问http://localhost:8081/user/hellxz001,注意使用token添加Bearer请求头

    相当于在Headers中添加 Authorization:Bearer 4a3c351d-770d-42aa-af39-3f54b50152e9

  • 资源正确返回

尾声

本文仅说明密码模式的精简化配置,某些部分如资源服务再访问授权服务去校验token这部分生产环境可能会换成Jwt、Redis等tokenStore实现,授权服务器中的用户信息与客户端信息生产环境应从数据库中读取,对应Spring Security的UserDetailsService实现类或用户信息的Provider等

最近发现博客写得相对较长,一方面有相当大的重复解释代码的部分,另一方面是代码很多不关键的地方也直接全贴出来了,博客长了代码全了,读者容易失去阅读的兴趣与探索实践的欲望。代码不全会直接贴出源码地址,暂时就这样,把这几篇关于OAuth2授权模式demo的文章赶出来

代码早就写完了,下周可能要开始加班了,先把这些已经完成的部分写出来,后续有什么新的知识点才有时间记

原文地址:https://www.cnblogs.com/hellxz/p/12041495.html

时间: 2024-11-07 09:37:46

Spring Security OAuth2 Demo —— 密码模式(Password)的相关文章

Spring Security OAuth2 Demo —— 客户端模式(ClientCredentials)

前情回顾 前几节分享了OAuth2的流程与其它三种授权模式,这几种授权模式复杂程度由大至小:授权码模式 > 隐式授权模式 > 密码模式 > 客户端模式 本文要讲的是最后一种也是最简单的模式:客户端模式 其中客户端模式的流程是:客户端使用授权服器给的标识与secret访问资源服务器获取token 本文目标 编写与说明密码模式的Spring Security Oauth2的demo实现,让未了解过相关知识的读者对客户端模式授权流程有个更直观的概念 以下分成授权服务器与资源服务器分别进行解释,

Spring Security OAuth2 Demo -- good

1. 添加依赖授权服务是基于Spring Security的,因此需要在项目中引入两个依赖: <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-security</artifactId> </dependency> <dependency> <groupId>org.springf

Spring Security OAuth2 授权码模式

 背景: 由于业务实现中涉及到接入第三方系统(app接入有赞商城等),所以涉及到第三方系统需要获取用户信息(用户手机号.姓名等),为了保证用户信息的安全和接入方式的统一, 采用Oauth2四种模式之一的授权码模式.  介绍:        第三方系统调用我方提供的授权接口(步骤1) 用户同意授权,后跳转第三方系统(步骤2.3) 第三方系统获得code,根据code到我方系统获取token(步骤5.6 ) 根据获取token访问受保护的资源(步骤8.9)    实际应用中由于合作商户,所以需要直接

springboot+spring security +oauth2.0 demo搭建(password模式)(认证授权端与资源服务端分离的形式)

项目security_simple(认证授权项目) 1.新建springboot项目 这儿选择springboot版本我选择的是2.0.6 点击finish后完成项目的创建 2.引入maven依赖  下面是我引入的依赖 1 <?xml version="1.0" encoding="UTF-8"?> 2 <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi=&q

Spring Security OAuth2

Spring Security OAuth2 标签(空格分隔): Spring 1. oAuth(Open Authorization) OAuth协议为用户资源的授权(增删改查)提供了一个安全, 开放而又简易的标准. 和以往授权方式不同之处是oAuth的授权不会使第三方触及到用户的账号信息. 即第三方无需使用用户的用户名和密码就可以申请获得该用户的资源授权. 因此oAuth本身第安全是无害的. 2. Spring Security Spring Security是一个安全框架, 可以为Spri

Spring security oauth2最简单入门环境搭建

关于OAuth2的一些简介,见我的上篇blog:http://wwwcomy.iteye.com/blog/2229889 PS:貌似内容太水直接被鹳狸猿干沉.. 友情提示 学习曲线:spring+spring mvc+spring security+Oauth2基本姿势,如果前面都没看过请及时关闭本网页. 我有信心我的这个blog应该是迄今为止使用spring security oauth2最简单的hello world app介绍了,如果你下下来附件源码还看不懂,请留言.. 其他能搜到的如h

【OAuth2.0】Spring Security OAuth2.0篇之初识

不吐不快 因为项目需求开始接触OAuth2.0授权协议.断断续续接触了有两周左右的时间.不得不吐槽的,依然是自己的学习习惯问题,总是着急想了解一切,习惯性地钻牛角尖去理解小的细节,而不是从宏观上去掌握,或者说先用起来(少年,一辈子辣么长,你这么着急合适吗?).好在前人们已经做好了很好的demo,我自己照着抄一抄也就理解了大概如何用,依旧手残党,依旧敲不出好代码.忏悔- WHAT? 项目之中实际使用OAuth2.0实现是用的Spring Security OAuth2.0,一套基于Spring S

Spring Security OAuth2 授权失败(401 问题整理

Spring Cloud架构中采用Spring Security OAuth2作为权限控制,关于OAuth2详细介绍可以参考 http://www.ruanyifeng.com/blog/2014/05/oauth_2_0.html 项目中采用OAuth2四种模式中的两种,Password模式和Client模式, Password模式用于控制用户的登录,Client模式用于控制后端服务相互调用. 权限架构调整后在近期发现一些问题,由于网上资料不多,只能单步调试方式看源码 (其实带着问题看源码是最

spring security oauth2 jwt 认证和资源分离的配置文件(java类配置版)

最近再学习spring security oauth2.下载了官方的例子sparklr2和tonr2进行学习.但是例子里包含的东西太多,不知道最简单最主要的配置有哪些.所以决定自己尝试搭建简单版本的例子.学习的过程中搭建了认证和资源在一个工程的例子,将token存储在数据库的例子等等 .最后做了这个认证和资源分离的jwt tokens版本.网上找了一些可用的代码然后做了一个整理, 同时测试了哪些代码是必须的.可能仍有一些不必要的代码在,欢迎大家赐教. 一.创建三个spring boot 工程,分