查看: 621|回复: 0

[Java学习] 架构师之路-如何构建rest接口的安全性访问(dubbox+oatuh2+rest)

发表于 2017-10-10 17:17:39
句号论坛
具体配置过程请参考:http://www.roncoo.com/course/view/ae1dbb70496349d3a8899b6c68f7d10b
建立oauth2认证需要的数据库及数据表结构
CREATE SCHEMA IF NOT EXISTS `oauth2` DEFAULT CHARACTER SET utf8 ;
USE `oauth2` ;
-- -----------------------------------------------------
-- Table `oauth2`.`clientdetails`
-- -----------------------------------------------------
CREATE TABLE IF NOT EXISTS `oauth2`.`clientdetails` (
  `appId` VARCHAR(128) NOT NULL,
  `resourceIds` VARCHAR(256) NULL DEFAULT NULL,
  `appSecret` VARCHAR(256) NULL DEFAULT NULL,
  `scope` VARCHAR(256) NULL DEFAULT NULL,
  `grantTypes` VARCHAR(256) NULL DEFAULT NULL,
  `redirectUrl` VARCHAR(256) NULL DEFAULT NULL,
  `authorities` VARCHAR(256) NULL DEFAULT NULL,
  `access_token_validity` INT(11) NULL DEFAULT NULL,
  `refresh_token_validity` INT(11) NULL DEFAULT NULL,
  `additionalInformation` VARCHAR(4096) NULL DEFAULT NULL,
  `autoApproveScopes` VARCHAR(256) NULL DEFAULT NULL,
  PRIMARY KEY (`appId`))
ENGINE = InnoDB
DEFAULT CHARACTER SET = utf8;
-- -----------------------------------------------------
-- Table `oatuh2`.`oauth_access_token`
-- -----------------------------------------------------
CREATE TABLE IF NOT EXISTS `oauth2`.`oauth_access_token` (
  `token_id` VARCHAR(256) NULL DEFAULT NULL,
  `token` BLOB NULL DEFAULT NULL,
  `authentication_id` VARCHAR(128) NOT NULL,
  `user_name` VARCHAR(256) NULL DEFAULT NULL,
  `client_id` VARCHAR(256) NULL DEFAULT NULL,
  `authentication` BLOB NULL DEFAULT NULL,
  `refresh_token` VARCHAR(256) NULL DEFAULT NULL,
  PRIMARY KEY (`authentication_id`))
ENGINE = InnoDB
DEFAULT CHARACTER SET = utf8;
-- -----------------------------------------------------
-- Table `oatuh2`.`oauth_approvals`
-- -----------------------------------------------------
CREATE TABLE IF NOT EXISTS `oauth2`.`oauth_approvals` (
  `userId` VARCHAR(256) NULL DEFAULT NULL,
  `clientId` VARCHAR(256) NULL DEFAULT NULL,
  `scope` VARCHAR(256) NULL DEFAULT NULL,
  `status` VARCHAR(10) NULL DEFAULT NULL,
  `expiresAt` DATETIME NULL DEFAULT NULL,
  `lastModifiedAt` DATETIME NULL DEFAULT NULL)
ENGINE = InnoDB
DEFAULT CHARACTER SET = utf8;
-- -----------------------------------------------------
-- Table `oatuh2`.`oauth_client_details`
-- -----------------------------------------------------
CREATE TABLE IF NOT EXISTS `oauth2`.`oauth_client_details` (
  `client_id` VARCHAR(128) NOT NULL,
  `resource_ids` VARCHAR(256) NULL DEFAULT NULL,
  `client_secret` VARCHAR(256) NULL DEFAULT NULL,
  `scope` VARCHAR(256) NULL DEFAULT NULL,
  `authorized_grant_types` VARCHAR(256) NULL DEFAULT NULL,
  `web_server_redirect_uri` VARCHAR(256) NULL DEFAULT NULL,
  `authorities` VARCHAR(256) NULL DEFAULT NULL,
  `access_token_validity` INT(11) NULL DEFAULT NULL,
  `refresh_token_validity` INT(11) NULL DEFAULT NULL,
  `additional_information` VARCHAR(4096) NULL DEFAULT NULL,
  `autoapprove` VARCHAR(256) NULL DEFAULT NULL,
  PRIMARY KEY (`client_id`))
ENGINE = InnoDB
DEFAULT CHARACTER SET = utf8;
-- -----------------------------------------------------
-- Table `oatuh2`.`oauth_client_token`
-- -----------------------------------------------------
CREATE TABLE IF NOT EXISTS `oauth2`.`oauth_client_token` (
  `token_id` VARCHAR(256) NULL DEFAULT NULL,
  `token` BLOB NULL DEFAULT NULL,
  `authentication_id` VARCHAR(128) NOT NULL,
  `user_name` VARCHAR(256) NULL DEFAULT NULL,
  `client_id` VARCHAR(256) NULL DEFAULT NULL,
  PRIMARY KEY (`authentication_id`))
ENGINE = InnoDB
DEFAULT CHARACTER SET = utf8;
-- -----------------------------------------------------
-- Table `oatuh2`.`oauth_code`
-- -----------------------------------------------------
CREATE TABLE IF NOT EXISTS `oauth2`.`oauth_code` (
  `code` VARCHAR(256) NULL DEFAULT NULL,
  `authentication` BLOB NULL DEFAULT NULL)
ENGINE = InnoDB
DEFAULT CHARACTER SET = utf8;
-- -----------------------------------------------------
-- Table `oatuh2`.`oauth_refresh_token`
-- -----------------------------------------------------
CREATE TABLE IF NOT EXISTS `oauth2`.`oauth_refresh_token` (
  `token_id` VARCHAR(256) NULL DEFAULT NULL,
  `token` BLOB NULL DEFAULT NULL,
  `authentication` BLOB NULL DEFAULT NULL)
ENGINE = InnoDB
DEFAULT CHARACTER SET = utf8;
>>前提:  使用Maven来管理项目; spring-security-oauth的版本号为 2.0.10.RELEASE

1. 添加Maven dependencies; 以下只列出了主要的


  •   
  • <dependency>  
  •     <groupId>org.springframework.securitygroupId>  
  •     <artifactId>spring-security-coreartifactId>  
  •     <version>${spring.security.version}version>  
  • dependency>  
  • <dependency>  
  •     <groupId>org.springframework.securitygroupId>  
  •     <artifactId>spring-security-webartifactId>  
  •     <version>${spring.security.version}version>  
  • dependency>  
  • <dependency>  
  •     <groupId>org.springframework.securitygroupId>  
  •     <artifactId>spring-security-taglibsartifactId>  
  •     <version>${spring.security.version}version>  
  • dependency>  
  • <dependency>  
  •     <groupId>org.springframework.securitygroupId>  
  •     <artifactId>spring-security-aclartifactId>  
  •     <version>${spring.security.version}version>  
  • dependency>  
  • <dependency>  
  •     <groupId>org.springframework.securitygroupId>  
  •     <artifactId>spring-security-cryptoartifactId>  
  •     <version>${spring.security.version}version>  
  • dependency>  
  • <dependency>  
  •     <groupId>org.springframework.securitygroupId>  
  •     <artifactId>spring-security-configartifactId>  
  •     <version>${spring.security.version}version>  
  • dependency>  
  •   
  • <dependency>  
  •     <groupId>org.springframework.security.oauthgroupId>  
  •     <artifactId>spring-security-oauth2artifactId>  
  •     <version>1.0.5.RELEASEversion>  
  • dependency>  



2. web.xml配置; 这一步与只使用Spring Security的配置一样.


  • pre><pre code_snippet_id="73897" snippet_file_name="blog_20131119_2_2257675" name="code" class="html">    <filter>  
  •         <filter-name>springSecurityFilterChainfilter-name>  
  •         <filter-class>org.springframework.web.filter.DelegatingFilterProxyfilter-class>  
  •     filter>  
  •   
  •     <filter-mapping>  
  •         <filter-name>springSecurityFilterChainfilter-name>  
  •         <url-pattern>/*url-pattern>  
  •     filter-mapping>  
  •   
  •       
  •     <context-param>  
  •         <param-name>contextConfigLocationparam-name>  
  •         <param-value>classpath:spring/*.xmlparam-value>  
  •     context-param>  
  •   
  •       
  •     <listener>  
  •         <listener-class>org.springframework.web.context.ContextLoaderListenerlistener-class>  
  •     listener>  
  •   
  •       
  •     <servlet>  
  •         <servlet-name>hyservlet-name>  
  •         <servlet-class>org.springframework.web.servlet.DispatcherServletservlet-class>  
  •         <load-on-startup>2load-on-startup>  
  •     servlet>  
  •     <servlet-mapping>  
  •         <servlet-name>hyservlet-name>  
  •         <url-pattern>/url-pattern>  
  •     servlet-mapping>  


对于Spring MVC, 需要配置文件hy-servlet.xml, 该文件不是这儿关注的(忽略);

在classpath创建spring目录, 在该目录里创建 security.xml 文件, 这是所有步骤配置的重点.

3.security.xml的配置; 重点开始.

3.1 起用注解; TokenEndpoint与AuthorizationEndpoint需要


  • <mvc:annotation-driven/>  
  • <mvc:default-servlet-handler/>  


3.2  TokenServices 配置

   1). TokenStore, 使用JdbcTokenStore, 将token信息存放数据库, 需要提供一个dataSource对象; 也可使用InMemoryTokenStore存于内存中


  •   
  • <beans:bean id="tokenStore" class="org.springframework.security.oauth2.provider.token.JdbcTokenStore">  
  •     <beans:constructor-arg index="0" ref="dataSource"/>  
  • beans:bean>  


注: 可以在spring-security-oauth2中找到对应的SQL脚本, 地址为https://github.com/spring-projects/spring-security-oauth/tree/master/spring-security-oauth2/src/test/resources, 目录中的schema.sql 即是. (以下不再说明SQL脚本的问题)


  2).TokenServices; 需要注入TokenStore


  • <beans:bean id="tokenServices" class="org.springframework.security.oauth2.provider.token.DefaultTokenServices">  
  •     <beans:property name="tokenStore" ref="tokenStore"/>  
  •     <beans:property name="supportRefreshToken" value="true"/>  
  • beans:bean>  


      如果允许刷新token 请将supportRefreshToken 的值设置为true, 默认为不允许

3.3 ClientDetailsService 配置, 使用JdbcClientDetailsService, 也需要提供dataSource, 替换demo中直接配置在配置文件中


  • <beans:bean id="clientDetailsService" class="org.springframework.security.oauth2.provider.JdbcClientDetailsService">  
  •     <beans:constructor-arg index="0" ref="dataSource"/>  
  • beans:bean>  



3.4 ClientDetailsUserDetailsService配置, 该类实现了Spring security中 UserDetailsService 接口


  • <beans:bean id="oauth2ClientDetailsUserService"  
  •             class="org.springframework.security.oauth2.provider.client.ClientDetailsUserDetailsService">  
  •     <beans:constructor-arg ref="clientDetailsService"/>  
  • beans:bean>  


3.5 OAuth2AuthenticationEntryPoint配置



  • <beans:bean id="oauth2AuthenticationEntryPoint"  
  •             class="org.springframework.security.oauth2.provider.error.OAuth2AuthenticationEntryPoint"/>  


3.6 oauth2 AuthenticationManager配置; 在整个配置中,有两个AuthenticationManager需要配置



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



第二个AuthenticationManager用于向获取UserDetails信息,

  • <authentication-manager alias="authenticationManager">  
  •     <authentication-provider user-service-ref="userService">  
  •         <password-encoder hash="md5"/>  
  •     authentication-provider>  
  • authentication-manager>  


userService是一个实现UserDetailsService的Bean

3.7 OAuth2AccessDeniedHandler配置, 实现AccessDeniedHandler接口


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


3.8 UserApprovalHandler配置, 这儿使用DefaultUserApprovalHandler, 这里是实现client是否可信任的关键点,你可以扩展该接口来自定义approval行为



  • <beans:bean id="oauthUserApprovalHandler" class="org.springframework.security.oauth2.provider.approval.DefaultUserApprovalHandler">  
  • beans:bean>  


3.9 authorization-server配置, 核心



  • <oauth2:authorization-server client-details-service-ref="clientDetailsService" token-services-ref="tokenServices"  
  •                              user-approval-handler-ref="oauthUserApprovalHandler">  
  •     <oauth2:authorization-code/>  
  •     <oauth2:implicit/>  
  •     <oauth2:refresh-token/>  
  •     <oauth2:client-credentials/>  
  •     <oauth2:password/>  
  • oauth2:authorization-server>  


该元素里面的每个标签可设置每一种authorized-grant-type的行为. 如disable refresh-token的配置为



  • <oauth2:refresh-token disabled="true"/>  



3.10 Oauth2 AccessDecisionManager配置, 这儿在默认的Spring Security AccessDecisionManager的基础上添加了ScopeVoter


  • <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>  


3.11 resource-server配置, 这儿定义两咱不同的resource



  •   
  • <oauth2:resource-server id="unityResourceServer" resource-id="unity-resource" token-services-ref="tokenServices"/>  
  •   
  •   
  • <oauth2:resource-server id="mobileResourceServer" resource-id="mobile-resource" token-services-ref="tokenServices"/>  


注意: 每个resource-id的值必须在对应的ClientDetails中resourceIds值中存在

3.12 ClientCredentialsTokenEndpointFilter配置, 该Filter将作用于Spring Security的chain 链条中


  • <beans:bean id="clientCredentialsTokenEndpointFilter"  
  •             class="org.springframework.security.oauth2.provider.client.ClientCredentialsTokenEndpointFilter">  
  •     <beans:property name="authenticationManager" ref="oauth2AuthenticationManager"/>  
  • beans:bean>  


3.13 /oauth/token 的http 配置, 用于监听该URL的请求, 核心



  • <http pattern="/oauth/token" create-session="stateless" authentication-manager-ref="oauth2AuthenticationManager"  
  •       entry-point-ref="oauth2AuthenticationEntryPoint">  
  •     <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"/>  
  • http>  


3.14 针对不同resource的http配置, 由于上面配置了两个resource, 这儿也配置两个



  •   
  • <http pattern="/unity/**" create-session="never" entry-point-ref="oauth2AuthenticationEntryPoint"  
  •       access-decision-manager-ref="oauth2AccessDecisionManager">  
  •     <anonymous enabled="false"/>  
  •   
  •     <intercept-url pattern="/unity/**" access="ROLE_UNITY,SCOPE_READ"/>  
  •   
  •     <custom-filter ref="unityResourceServer" before="PRE_AUTH_FILTER"/>  
  •     <access-denied-handler ref="oauth2AccessDeniedHandler"/>  
  • http>  
  •   
  •   
  • <http pattern="/m/**" create-session="never" entry-point-ref="oauth2AuthenticationEntryPoint"  
  •       access-decision-manager-ref="oauth2AccessDecisionManager">  
  •     <anonymous enabled="false"/>  
  •   
  •     <intercept-url pattern="/m/**" access="ROLE_MOBILE,SCOPE_READ"/>  
  •   
  •     <custom-filter ref="mobileResourceServer" before="PRE_AUTH_FILTER"/>  
  •     <access-denied-handler ref="oauth2AccessDeniedHandler"/>  
  • http>  

注意每一个http对应不同的resourceServer. access-decison-manager-ref对应Oauth的AccessDecisionManager


3.15 默认的http配置,给/oauth/** 设置权限


  • <http access-denied-page="/login.jsp?authorization_error=2" disable-url-rewriting="true"  
  •       authentication-manager-ref="authenticationManager">  
  •     <intercept-url pattern="/oauth/**" access="ROLE_USER,ROLE_UNITY,ROLE_MOBILE"/>  
  •     <intercept-url pattern="/**" access="IS_AUTHENTICATED_ANONYMOUSLY"/>  
  •   
  •     <form-login authentication-failure-url="/login.jsp?authentication_error=1" default-target-url="/index.jsp"  
  •                 login-page="/login.jsp" login-processing-url="/login.do"/>  
  •     <logout logout-success-url="/index.jsp" logout-url="/logout.do"/>  
  •     <anonymous/>  
  • http>  




到此, securiy.xml 配置完毕.

当然,还有些额外的工作你需要做, 如配置dataSource, 创建数据库, 添加用户用户信息, 管理ClientDetails等等.
Oauth相关的数据都是存放在数据库, 我们就可以根据表结果创建domain来实现管理.



太阳http代理AD
回复

使用道具 举报

关闭

站长推荐上一条 /1 下一条