zoukankan      html  css  js  c++  java
  • 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介绍了,如果你下下来附件源码还看不懂,请留言。。 

    其他能搜到的如http://blog.csdn.net/monkeyking1987/article/details/16828059这个哥们儿 
    和 
    http://www.cnblogs.com/smarterplanet/p/4088479.html 
    这个,都很好,不过因为依赖了数据库,配置比较多,对于初学者来说,搭起来一个最最简单的环境才是最重要的,撸要一步一步走嘛(如果对spring不是特别熟,强烈不建议看官方的tutorial,槽点太多,例如静态JS库的引用方式,web.xml的使用方式,Spring的配置方式,我反正下下来就惊呆了,第一次看到用java代码配spring) 

    基本需求: 
    用户A希望授权网站B能获取自己在网站appDemo的一个资源,资源的地址是 
    http://localhost:8080/appDemo/resource/getUserInfo 

    使用的框架及版本: 
    • spring-webmvc 3.2.8
    • spring-security-web 3.2.6
    • spring-security-oauth2 2.0.7 (这是到2015.7为止的最新版本,和1.0有些小区别,我也在这上面卡了一段时间)

    Pom文件见附件整个项目源码。 

    准备材料(附件都已经包括): 
    • 搭建一个springMVC+springSecurity的最简单环境,并且自定义一个login.jsp
    • 写一个controller和Jsp,充当用户的受保护资源
    • 写两个jsp作为scope选择确认页面


    我们要做的 
    仅仅是配置spring security的配置文件就可以了~一点代码都不用写,数据库也不用连。 

    我会从client信息开始,把整个配置文件串起来,最后我会讲appDemo使用的方法,和以下的配置联系起来 

    • 网站B在网站appDemo的"用户"(注意这里和用户A没半毛钱关系)信息,即client_id和client_secret配置:
    Xml代码  收藏代码
    1. <authentication-manager id="clientAuthenticationManager">  
    2.         <authentication-provider user-service-ref="oauth2ClientDetailsUserService" />  
    3.     </authentication-manager>  
    4.     <beans:bean id="oauth2ClientDetailsUserService"  
    5.     class="org.springframework.security.oauth2.provider.client.ClientDetailsUserDetailsService">  
    6.         <beans:constructor-arg ref="clientDetailsService" />  
    7.     </beans:bean>  
    8. <oauth2:client-details-service id="clientDetailsService">  
    9.         <oauth2:client client-id="m1"  
    10.             authorized-grant-types="password,authorization_code,refresh_token,implicit"  
    11.             secret="s1" scope="read,write,trust" authorities="ROLE_CLIENT, ROLE_TRUSTED_CLIENT"  
    12.             resource-ids="pic-resource" />  
    13.     </oauth2:client-details-service>  

    注意命名空间,可以看到client配置和spring security传统的用户配置是非常像的。 
    这里配置了网站B在appDemo中的client_id,client_secret,scope,权限和授权类型,资源ID,那这个资源ID是个啥呢? 
    • 资源filter配置:
    Xml代码  收藏代码
    1. <oauth2:resource-server id="picResourceServer"  
    2.         resource-id="pic-resource" token-services-ref="tokenServices" />  

    配置这个,除了资源定位(id),还为了给我们的资源加上一个自定义的OAuth过滤器,这个过滤器主要是为了网站B在访问资源的时候验证Access Token。然后出现了两个分支: 
    1.配token service 
    2.配资源 
    • 先讲Token配置:
    Xml代码  收藏代码
    1. <beans:bean id="tokenServices"  
    2.         class="org.springframework.security.oauth2.provider.token.DefaultTokenServices">  
    3.         <beans:property name="tokenStore" ref="tokenStore" />  
    4.         <beans:property name="supportRefreshToken" value="true" />  
    5.         <beans:property name="clientDetailsService" ref="clientDetailsService" />  
    6.     </beans:bean>  
    7.     <beans:bean id="tokenStore"  
    8.         class="org.springframework.security.oauth2.provider.token.store.InMemoryTokenStore">  
    9.     </beans:bean>  

    我们把Token存在内存里,摆脱数据库依赖。想象一下,为了生成和client相关的token,肯定需要把上面提到的ClientService配置进去 

    • 资源和资源的保护
    Xml代码  收藏代码
    1. <http pattern="/resource/**" create-session="never"  
    2.         entry-point-ref="oauth2AuthenticationEntryPoint"  
    3.         access-decision-manager-ref="oauth2AccessDecisionManager">  
    4.         <anonymous enabled="false" />  
    5.         <intercept-url pattern="/resource/**" access="ROLE_USER,SCOPE_READ" />  
    6.         <custom-filter ref="picResourceServer" before="PRE_AUTH_FILTER" />  
    7.         <access-denied-handler ref="oauthAccessDeniedHandler" />  
    8.     </http>  

    这是spring security的传统配置了,除了我们刚才提到的资源filter,还配置了认证失败、授权失败的处理,和判断是否可访问的"access decision manager" 
    • 认证失败,授权失败
    Xml代码  收藏代码
    1. <beans:bean id="oauth2AuthenticationEntryPoint"  
    2.         class="org.springframework.security.oauth2.provider.error.OAuth2AuthenticationEntryPoint" />  
    3.   
    4.     <beans:bean id="oauthAccessDeniedHandler"  
    5.         class="org.springframework.security.oauth2.provider.error.OAuth2AccessDeniedHandler" />  

    这个没什么好解释的了,其实作为demo也可以不配,毕竟我们应该会一路按能跑通的先跑。 
    • access decision manager
    Xml代码  收藏代码
    1. <beans:bean id="oauth2AccessDecisionManager"  
    2.         class="org.springframework.security.access.vote.UnanimousBased">  
    3.         <beans:constructor-arg>  
    4.             <beans:list>  
    5.                 <beans:bean  
    6.                     class="org.springframework.security.oauth2.provider.vote.ScopeVoter" />  
    7.                 <beans:bean class="org.springframework.security.access.vote.RoleVoter" />  
    8.                 <beans:bean  
    9.                     class="org.springframework.security.access.vote.AuthenticatedVoter" />  
    10.             </beans:list>  
    11.         </beans:constructor-arg>  
    12.     </beans:bean>  

    也是传统的配置方法了,多了个oauth2里面特有的scope投票机制。 

    好,到现在为止,OAuth2 Server所需要的所有龙珠都已经集齐,接下来就可以召唤神龙了 
    • 出来吧!神龙
    Xml代码  收藏代码
    1. <oauth2:authorization-server  
    2.         client-details-service-ref="clientDetailsService" token-services-ref="tokenServices"  
    3.         user-approval-handler-ref="oauthUserApprovalHandler"  
    4.         user-approval-page="oauth_approval" error-page="oauth_error">  
    5.         <oauth2:authorization-code />  
    6.         <oauth2:implicit />  
    7.         <oauth2:refresh-token />  
    8.         <oauth2:client-credentials />  
    9.         <oauth2:password />  
    10.     </oauth2:authorization-server>  
    11.   
    12.     <beans:bean id="oauthUserApprovalHandler"  
    13.         class="org.springframework.security.oauth2.provider.approval.DefaultUserApprovalHandler" />  


    还差两步: 
    1.网站B来申请Token时候的认证和权限设置: 
    Xml代码  收藏代码
    1. <http pattern="/oauth/token" create-session="stateless"  
    2.         authentication-manager-ref="clientAuthenticationManager"  
    3.         entry-point-ref="oauth2AuthenticationEntryPoint">  
    4.         <intercept-url pattern="/oauth/token" access="IS_AUTHENTICATED_FULLY" />  
    5.         <anonymous enabled="false" />  
    6.         <http-basic entry-point-ref="oauth2AuthenticationEntryPoint" />  
    7.         <custom-filter ref="clientCredentialsTokenEndpointFilter"  
    8.             before="BASIC_AUTH_FILTER" />  
    9.         <access-denied-handler ref="oauthAccessDeniedHandler" />  
    10.     </http>  
    11.   
    12.     <beans:bean id="clientCredentialsTokenEndpointFilter"  
    13.         class="org.springframework.security.oauth2.provider.client.ClientCredentialsTokenEndpointFilter">  
    14.         <beans:property name="authenticationManager" ref="clientAuthenticationManager" />  
    15.     </beans:bean>  


    2.作为屌丝用户A,认证放在配置最后了(也应该放在前面那个http的后面,因为这里有个全局匹配了) 
    Xml代码  收藏代码
    1. <http access-denied-page="/login.jsp?error=true"  
    2.         authentication-manager-ref="authenticationManager">  
    3.         <intercept-url pattern="/oauth/**" access="ROLE_USER" />  
    4.         <intercept-url pattern="/**" access="IS_AUTHENTICATED_ANONYMOUSLY" />  
    5.         <form-login login-page="/login.jsp"  
    6.             authentication-failure-url="/login.jsp?error=true"  
    7.             default-target-url="/index.jsp" />  
    8.         <anonymous />  
    9.     </http>  
    10.   
    11.     <authentication-manager alias="authenticationManager">  
    12.         <authentication-provider>  
    13.             <user-service id="userService">  
    14.                 <user name="admin" password="admin" authorities="ROLE_USER" />  
    15.             </user-service>  
    16.         </authentication-provider>  
    17.     </authentication-manager>  


    写到这里,我默默预览了一下,估计群众们看到这句话大都是拖滚轴下来的。 

    不过配置真的挺长,不花篇幅真讲不清楚。 

    最后把大致流程和配置关联一下: 

      • *.用户要授权网站B获取appDemo资源
      • 1.网站B把用户跳转到appDemo/oauth/authorize?client_id=m1&redirect_uri=http%3a%2f%2flocalhost%3a8080%2f&response_type=code&scope=read

        Spring Security Oauth2有一个controller:AuthorizationEndpoint处理这个请求,这个是不用配置的。 但是在controller处理之前,appDemo发现,我擦嘞,用户还没登录啊(见屌丝用户A认证配置)!于是先跳转到登录界面让用户登录。 

    • 2.用户登录成功后,跳转到了scope选择确认页面(见出现吧!神龙)。
    • 3.appDemo生成了Authorization Code并跳转回网站B(其实神龙的authorization-code这种配置方式有其他的配置项,可以选填Authorzation code service)
    • 4.网站B拿到了code,向appDemo请求accessToken(appDemo/oauth/token?code=g6hW13&client_id=m1&client_secret=s1&grant_type=authorization_code&redirect_uri=http%3a%2f%2flocalhost%3a8080%2f)
    • 网站B的client认证配置起作用了,AccessDecisionManager起作用了,资源信息起作用了,Token生成也起作用了。
    • 5.最后网站B通过access token访问资源,资源和资源的保护配置起作用了。


    具体的使用流程在appDemo的index页面有步骤。 

    完。
  • 相关阅读:
    Linux 环境下搭建单机版 Redis
    为什么要同时重写equals和hashcode方法
    使用ThreadPoolExecutor 创建线程池,完成并行操作
    一个简单的通过newFixedThreadPool实现多线程案例
    Java 获取对象的所有属性及其对应的值
    分布式id生成方案总结
    使用idea和gradle编译spring5源码
    Pandas中常用的函数使用
    单链表的反转 python实现实例
    kaggle注册中的坑---2018,12.3试过有效
  • 原文地址:https://www.cnblogs.com/mingjian/p/5704223.html
Copyright © 2011-2022 走看看