文档章节

spring security oauth2

 凌晨一点半
发布于 2016/02/27 00:00
字数 1623
阅读 636
收藏 15

最近在学习spring security Oauth2 认证,github中官方demo 不敢恭维 完全看不懂,网络上 http://blog.csdn.net/monkeyking1987/article/details/16828059 这篇博客 清楚的说明 相关的配置以及 各组件功能。推荐大家学习。这里也是参考这位大神的作品,一点点搭建,debug。记录下搭建过程中的一些心得 和认识,方便以后项目中参考。

   spring security 的鉴权 是通过  servlet filter 过滤器 去处理,封装相关的请求,通过过滤器链,按部就班的进行数据封装,数据校验,数据鉴权,异常处理,视图渲染等操作。可参考 http://haohaoxuexi.iteye.com/blog/2154299 系列博客初步了解spring security相关机制和配置。

    oauth2 是一种授权协议,可参考 http://www.ruanyifeng.com/blog/2014/05/oauth_2_0.html 非常经典的文章说明了oauth2 原理。

从理论上说 放在我们面前所要做的就是1.授权2.获取token 3.利用token进行资源访问,由spring security框架进行权限的校验,决定token拥有者是否有权限进行资源的操作。

1、授权

spring security Oauth2 通过自身实现的 AuthorizationEndpoint 基于 /oauth/authorize handler 去处理用户提交用户名/密码 进行授权的操作。主要是相关参数校验,并对授权身份(principal)进行手否已通过认证校验(身份的获取认证是通过spring security框架中的filter完成校验),如果不是会抛出相关异常,相关异常由其相应的异常处理过滤器显示相关提示异常信息(如无效的appkey等)。当都通过后根据responseType判断如果是 授权码(code)相应 直接跳转到授权许可页面(两个按钮。授权 & 取消),如果是简化模式("token")生产 简化模式access_token 对象响应。

在授权码模式下的授权许可页面中,点击许可或者取消 访问的依然是 /oauth/authorize ,AuthorizationEndpoint利用@RequestMapping 中的 params参数中存在 USER_OAUTH_APPROVAL = "user_oauth_approval" 参数进行handler的区分处理。这步操作主要是针对用户授权许可后重定向到指定第三方服务器url并添加 生成的授权码给第三方应用。

2.获取token

用户获取token的方式,客户端通过不同的授权模式访问TokenEndPoint 控制器下的/oauth/token 申请获取token,其中会对client_Id和 client_secret(username&password (密码模式下),通过spring 通用AuthenticationManager进行用户名密码校验)等进行校验。这些校验是通过oauth2AuthenticationManager进行校验,并生成authennted=true的身份,当 /oauth/token handler 处理时校验相关参数和认证后,基于具体的业务逻辑获取当前用户当前第三方应用的token信息返回给第三方,这里至于如果基于顾虑器校验 以及token生成策略 忽略,有兴趣可查看源码。

3.访问第三方资源

用户在访问具体资源url的时候 在请求参数中附带access_token 信息 即可被资源服务器(resource Server实质上就是个Filter)拦截进行相关权限校验。

可能描述的不太清楚,大家可以在每个<http>中的过滤器debug 查看每次操作 过滤器的相关对象包装以及校验逻辑。最重要的是把握  /oauth/authorize 和 /oauth/token 两个handler 以及过滤器链的配置。

附上spring security Oauth2  相关配置文件:

<?xml version="1.0" encoding="UTF-8"?>
<beans:beans xmlns="http://www.springframework.org/schema/security"
             xmlns:beans="http://www.springframework.org/schema/beans"
             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xmlns:oauth2="http://www.springframework.org/schema/security/oauth2"
             xmlns:mvc="http://www.springframework.org/schema/mvc"
             xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
                        http://www.springframework.org/schema/security
                        http://www.springframework.org/schema/security/spring-security-4.0.xsd http://www.springframework.org/schema/security/oauth2 http://www.springframework.org/schema/security/spring-security-oauth2-2.0.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.0.xsd">

    <!-- 默认 接口初始化 -->
    <mvc:annotation-driven/>
    <mvc:default-servlet-handler/>

    <!--获取token请求拦截-->
    <http pattern="/oauth/token" create-session="stateless" authentication-manager-ref="oauth2AuthenticationManager"
          entry-point-ref="oauth2AuthenticationEntryPoint" use-expressions="false">
        <intercept-url pattern="/oauth/token" access="IS_AUTHENTICATED_FULLY"/>
        <anonymous enabled="false"/>
        <http-basic entry-point-ref="oauth2AuthenticationEntryPoint"/>

        <custom-filter ref="clientCredentialsTokenEndpointFilter" before="BASIC_AUTH_FILTER"/>
        <access-denied-handler ref="oauth2AccessDeniedHandler"/>
        <csrf disabled="true"/>
    </http>

    <!--web resource 拦截 配置-->
    <http pattern="/web/**" create-session="never" entry-point-ref="oauth2AuthenticationEntryPoint"
          access-decision-manager-ref="oauth2AccessDecisionManager" use-expressions="false">
        <anonymous enabled="false"/>

        <intercept-url pattern="/web/**" access="ROLE_WEB,SCOPE_READ"/>

        <custom-filter ref="webResourceServer" before="PRE_AUTH_FILTER"/>
        <access-denied-handler ref="oauth2AccessDeniedHandler"/>
        <csrf disabled="true"/>
    </http>

    <!--mobile resource 拦截配置-->
    <http pattern="/mobile/**" create-session="never" entry-point-ref="oauth2AuthenticationEntryPoint"
          access-decision-manager-ref="oauth2AccessDecisionManager" use-expressions="false">
        <anonymous enabled="false"/>

        <intercept-url pattern="/mobile/**" access="ROLE_MOBILE,SCOPE_READ"/>

        <custom-filter ref="mobileResourceServer" before="PRE_AUTH_FILTER"/>
        <access-denied-handler ref="oauth2AccessDeniedHandler"/>
        <csrf disabled="true"/>
    </http>

    <http disable-url-rewriting="true" use-expressions="false"
          authentication-manager-ref="authenticationManager">
        <intercept-url pattern="/oauth/**" access="ROLE_WEB,ROLE_MOBILE"/>
        <intercept-url pattern="/**" access="IS_AUTHENTICATED_ANONYMOUSLY"/>

        <form-login authentication-failure-url="/login?error=10001" default-target-url="/index.jsp"
                    login-page="/login" login-processing-url="/login.do"
                    username-parameter="username" password-parameter="password"/>
        <logout logout-success-url="/index.jsp" logout-url="/logout"/>
        <access-denied-handler error-page="/login?error=20002"/>
        <anonymous/>
        <csrf disabled="true"/>
    </http>


    <!--oauth 授权服务器配置-->
    <!--user-approval-handler-ref="oauthUserApprovalHandler"
                                   user-approval-page="oauth_approval"error-page="oauth_error-->
    <oauth2:authorization-server  client-details-service-ref="clientDetailsService" token-services-ref="tokenServices"
                                  error-page="/oauth/error">
        <oauth2:authorization-code authorization-code-services-ref="jdbcAuthorizationCodeServices"/>
        <oauth2:implicit/>
        <oauth2:refresh-token/>
        <oauth2:client-credentials/>
        <oauth2:password/>
    </oauth2:authorization-server>


    <!-- 基础服务配置-->

    <!--/oauth/token 请求token时候 定义的拦截器用于封装clientId 和 client_secret
    成UsernamePasswordAuthenticationToken 进行校验(和普通的spring scurity 认证相似,注入oauth2 认证器校验)  -->
    <beans:bean id="clientCredentialsTokenEndpointFilter"
                class="org.springframework.security.oauth2.provider.client.ClientCredentialsTokenEndpointFilter">
        <beans:property name="authenticationManager" ref="oauth2AuthenticationManager"/>
    </beans:bean>

    <!--配置资源服务器 : 本质是被spring 读取s
    chema配置生成一个filter 添加到filterchain中 这样还是利用了spring scurity 拦截器进行拦截鉴权-->
    <!--web resource server filter-->
    <oauth2:resource-server id="webResourceServer" resource-id="unity-resource" token-services-ref="tokenServices"/>

    <!--mobile resource server filter-->
    <oauth2:resource-server id="mobileResourceServer" resource-id="mobile-resource" token-services-ref="tokenServices"/>

    <!-- 资源服务器需要的 clientDetailService 用于加载clientDetail等信息-->
    <beans:bean id="clientDetailsService" class="org.springframework.security.oauth2.provider.client.JdbcClientDetailsService">
        <beans:constructor-arg name="dataSource" ref="dataSource"/>
    </beans:bean>

    <!--配置tokenservice -->
    <!-- token 和刷新token的原子操作服务 DAO-->
    <beans:bean id="tokenStore" class="org.springframework.security.oauth2.provider.token.store.JdbcTokenStore">
        <beans:constructor-arg index="0" ref="dataSource"/>
    </beans:bean>

    <beans:bean id="tokenServices" class="org.springframework.security.oauth2.provider.token.DefaultTokenServices">
        <beans:property name="tokenStore" ref="tokenStore"/>
        <beans:property name="clientDetailsService" ref="clientDetailsService"/>
        <beans:property name="supportRefreshToken" value="true"/>
        <!--设置token 有效时间 可以在clientDetail为每一个注册第三方应用设置token的有效时间 也可以设置通用有效时间
                 spring security 默认有效时间为 12个小时-->
        <!--<beans:property name="accessTokenValiditySeconds" value="1000"/>
        <beans:property name="refreshTokenValiditySeconds" value="2000"/>-->
    </beans:bean>

    <!--授权码服务 授权码 增删查-->
    <beans:bean id="jdbcAuthorizationCodeServices"
                class="org.springframework.security.oauth2.provider.code.JdbcAuthorizationCodeServices">
        <beans:constructor-arg index="0" ref="dataSource"/>
    </beans:bean>

    <!--/oauth/authorize 获取授权拦截 使用spring security 通用 uname*Filter 处理 -->
    <authentication-manager alias="authenticationManager" >
        <authentication-provider user-service-ref="customUserDetailsService">
            <password-encoder hash="md5"/>
        </authentication-provider>
    </authentication-manager>

    <!--entryPoint 异常时处理接口 -->
    <beans:bean id="oauth2AuthenticationEntryPoint"
                class="org.springframework.security.oauth2.provider.error.OAuth2AuthenticationEntryPoint"/>

    <!--客户端应用 详情服务 设计-->
    <beans:bean id="oauth2ClientDetailsUserService"
                class="org.springframework.security.oauth2.provider.client.ClientDetailsUserDetailsService">
        <beans:constructor-arg ref="clientDetailsService"/>
    </beans:bean>

    <authentication-manager id="oauth2AuthenticationManager">
        <authentication-provider user-service-ref="oauth2ClientDetailsUserService"/>
    </authentication-manager>

    <beans:bean id="oauth2AccessDecisionManager" class="org.springframework.security.access.vote.UnanimousBased">
        <beans:constructor-arg>
            <beans:list>
                <beans:bean class="org.springframework.security.oauth2.provider.vote.ScopeVoter"/>
                <beans:bean class="org.springframework.security.access.vote.RoleVoter"/>
                <beans:bean class="org.springframework.security.access.vote.AuthenticatedVoter"/>
            </beans:list>
        </beans:constructor-arg>
    </beans:bean>

    <beans:bean id="oauth2AccessDeniedHandler"
                class="org.springframework.security.oauth2.provider.error.OAuth2AccessDeniedHandler"/>

    <beans:bean id="customUserDetailsService" class="com.hrd.udb.security.CustomUserDetailsService"/>

</beans:beans>



© 著作权归作者所有

下一篇: EhCache
粉丝 3
博文 11
码字总数 6819
作品 0
合肥
程序员
私信 提问
Secures your applications with Spring Security 5 and Keycloak

Spring Security 5 brought new OAuth2/OIDC client instead of the legacy client support in the old Spring Security OAuth sub project. The new OAuth2 umbrella modules in the core p......

hantsy
2018/04/24
152
0
Spring Security 从入门到进阶系列教程

Spring Security 入门系列 《保护 Web 应用的安全》 《Spring-Security-入门(一):登录与退出》 《Spring-Security-入门(二):基于数据库验证》 《Spring-Security-入门(三):密码加密...

小致Daddy
2018/08/03
16.1K
1
spring-security-oauth2-boot 2.0.3 发布

spring-security-oauth2-boot 2.0.3 已发布。该项目提供 了spring-security-oauth2 和 Spring Boot 2 的集成(即自动配置)。 未发现具体的更新说明,由提交信息可知, 主要是修复了关于 Sp...

淡漠悠然
2018/08/17
783
0
spring-oauth-server 0.4 发布, Oauth2 与 Spring Security 安全应用整合

在spring-oauth-server 0.4-beta版本从2015-11-18发布一个多月后, 0.4版本正式发布. 在这期间主要测试各项新增功能. spring-oauth-server 是一个整合Oauth2与Spring Security的安全应用项目,...

monkeyk7
2016/01/02
1K
0
Spring Boot Security 整合 OAuth2 设计安全API接口服务

文章首发于公众号《程序员果果》 地址:https://mp.weixin.qq.com/s/0PAUErDh0qmcR4SUsTn15Q 简介 OAuth是一个关于授权(authorization)的开放网络标准,在全世界得到广泛应用,目前的版本是...

公众号:程序员果果
05/21
0
0

没有更多内容

加载失败,请刷新页面

加载更多

CentOS7.6中安装使用fcitx框架

内容目录 一、为什么要使用fcitx?二、安装fcitx框架三、安装搜狗输入法 一、为什么要使用fcitx? Gnome3桌面自带的输入法框架为ibus,而在使用ibus时会时不时出现卡顿无法输入的现象。 搜狗和...

技术训练营
昨天
5
0
《Designing.Data-Intensive.Applications》笔记 四

第九章 一致性与共识 分布式系统最重要的的抽象之一是共识(consensus):让所有的节点对某件事达成一致。 最终一致性(eventual consistency)只提供较弱的保证,需要探索更高的一致性保证(stro...

丰田破产标志
昨天
8
0
docker 使用mysql

1, 进入容器 比如 myslq1 里面进行操作 docker exec -it mysql1 /bin/bash 2. 退出 容器 交互: exit 3. mysql 启动在容器里面,并且 可以本地连接mysql docker run --name mysql1 --env MY...

之渊
昨天
10
0
python数据结构

1、字符串及其方法(案例来自Python-100-Days) def main(): str1 = 'hello, world!' # 通过len函数计算字符串的长度 print(len(str1)) # 13 # 获得字符串首字母大写的...

huijue
昨天
6
0
PHP+Ajax微信手机端九宫格抽奖实例

PHP+Ajax结合lottery.js制作的一款微信手机端九宫格抽奖实例,抽奖完成后有收货地址添加表单出现。支持可以设置中奖概率等。 奖品列表 <div class="lottery_list clearfix" id="lottery"> ......

ymkjs1990
昨天
5
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部