【JavaEE】SSH+Spring Security+Spring oauth2环境方法及example

原文  http://www.cnblogs.com/smarterplanet/p/4088479.html

现在加最后一样,就是oauth2,现在很多网站都有对应的移动版本,那么移动端访问服务端的服务怎么控制权限,我知道的主要是两种方法,第一是模拟浏览器,访问服务的时候会生成session,之后在移动端缓存cookie,每次网络请求都把cookie加上,还有一种就是通过oauth2,登录之后生成一个凭证,每次请求时携带凭证,当然oauth2更多的是为第三方应用提供访问自己服务的权限。

oauth2的配置,可以纯配置文件打造,相比较前面的那些,可以说是最简单也是最复杂的,简单是因为引入jar包配置一个xml就可以,复杂是说这个仅有的xml需要写的东西很多理解起来也要费劲。

关于Oauth2的整合,很大程度上参考了这位仁兄的文章: http://blog.csdn.net/monkeyking1987/article/details/16828059 。

1. pom.xml

首先导入oauth2的包:

<properties>
  ……
  <spring-security-oauth2.version>2.0.2.RELEASE</spring-security-oauth2.version>
</properties>

<dependencies>
  ……
  <dependency>
    <groupId>org.springframework.security.oauth</groupId>
    <artifactId>spring-security-oauth2</artifactId>
    <version>${spring-security-oauth2.version}</version>
  </dependency>
  ……
</dependencies>

2. applicationContext-security.xml

oauth2是security的一部分,配置也有关联,就不再单建文件,首先要在最前面加一些schema:

<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"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
      http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
      http://www.springframework.org/schema/security/oauth2
      http://www.springframework.org/schema/security/spring-security-oauth2-1.0.xsd
      http://www.springframework.org/schema/security
      http://www.springframework.org/schema/security/spring-security-3.2.xsd">

其实就是加了一个oauth2的命名。

在这个文件的开始,也就是之前配置的拦截链的http标签前面并列一个http标签:

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

这个标签处理/oauth/token的网络请求,这是oauth2的登录验证请求,那么登录需要什么,首先,和Spring Security一样,需要一个认证管理器,Spring Oauth2需要两个认证管理器,第一个就是之前Spring中配置的那一个,用来验证用户名密码的,还有一个是用来区分客户端用户的,给它起个名字叫oauth2AuthenticationManager:

<oauth2:client-details-service id="clientDetailsService">
    <oauth2:client client-id="mobile_1" authorized-grant-types="password,authorization_code,refresh_token,implicit"
                secret="secret_1"scope="read,write,trust" />
</oauth2:client-details-service>
<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>

这儿设置了一种客户端,id叫做mobile_1,secret叫做secret_1,针对read、write和trust几个域有效。这几个域会在访问控制中被用到。

当登录成功之后会得到一个token,再次访问的时候需要携带这个token,spring-oauth2根据这个token来做认证,那么spring-oauth2必须先存一份token和用户关系的对应,因为不用session了,这就相当于session,那么这个token在服务器中怎么存,有两种主要的存储方式,一是创建数据表,把token存到数据库里,我现在追求简单可用,采用第二种方式,直接存到内存里。下面配置一个管理token的service:

<beans:bean id="tokenStore" class="org.springframework.security.oauth2.provider.token.store.InMemoryTokenStore"/>
<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>

下面配置4个基本的bean:分别处理访问成功、访问拒绝、认证点和访问控制:

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

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

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

下一步,配置这个oauth2的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>

比如说,如果配置本服务器不支持刷新token,那么就:

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

我们的请求里,要把验证类型、用户名密码都作为表单参数提交,这就需要配置下面的filter:

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

下面定义一种资源,指定spring要保护的资源,如果没有这个,访问控制的时候会说没有Authentication object:

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

好了,到此为止基本配置就都有了,下面就看访问控制的配置:在前面的拦截链上,已经为登录验证配了一个/auth/token,在这个标签下面添加对/json和/admin这两个路径的控制(这里没有再写这两个访问的controller,依旧用前面几篇文章中写好的):

<http pattern="/json**" create-session="never"
  entry-point-ref="oauth2AuthenticationEntryPoint"
  access-decision-manager-ref="oauth2AccessDecisionManager">
    <anonymous enabled="false" />
    <intercept-url pattern="/json**" access="ROLE_USER" />
    <custom-filter ref="mobileResourceServer" before="PRE_AUTH_FILTER" />
    <access-denied-handler ref="oauth2AccessDeniedHandler" />
</http>
<http pattern="/admin**" create-session="never"
  entry-point-ref="oauth2AuthenticationEntryPoint"
  access-decision-manager-ref="oauth2AccessDecisionManager">
    <anonymous enabled="false" />
    <intercept-url pattern="/admin**" access="ROLE_ADMIN,SCOPE_READ" />
    <custom-filter ref="mobileResourceServer" before="PRE_AUTH_FILTER" />
    <access-denied-handler ref="oauth2AccessDeniedHandler" />
</http>

我们用oauth2AccessDecisionManager来做决策,这个地方需要注意,spring-security里面配置access="ROLE_USER,ROLE_ADMIN"是说user和admin都可以访问,是一个“或”的关系,但是这里是“与”的关系,比如第二个,需要ROLE_ADMIN并且当前的scope包含read才可以,否则就没有权限。认证失败会返回一段xml,这个可以自定义handler来修改,暂且按下不表。 源码下载 。

ps:使用方法:用户名密码前面spring-security中已经创建了用户,验证身份时访问:

http://localhost:8080/demo4ssh-security-oauth2/oauth/token?client_id=mobile_1&client_secret=secret_1&grant_type=password&username=zhangsan&password=123456

这时候会返回一个access_token:

{"access_token":"4219a91f-45d5-4a07-9e8e-3acbadd0c23e","token_type":"bearer","refresh_token":"d41df9fd-3d36-4a20-b0b7-1a1883c7439d","expires_in":43199,"scope":"read write trust"}

这之后再拿着这个access_token去访问资源:

http://localhost:8080/demo4ssh-security-oauth2/admin?access_token=4219a91f-45d5-4a07-9e8e-3acbadd0c23e

附保存至数据库时数据库结构:
-- used in tests that use HSQL
  create table oauth_client_details (
  client_id VARCHAR(256) PRIMARY KEY,
  resource_ids VARCHAR(256),
  client_secret VARCHAR(256),
  scope VARCHAR(256),
  authorized_grant_types VARCHAR(256),
  web_server_redirect_uri VARCHAR(256),
  authorities VARCHAR(256),
  access_token_validity INTEGER,
  refresh_token_validity INTEGER,
  additional_information VARCHAR(4096),
  autoapprove VARCHAR(256)
  );
   
  create table oauth_client_token (
  token_id VARCHAR(256),
  token LONGVARBINARY,
  authentication_id VARCHAR(256) PRIMARY KEY,
  user_name VARCHAR(256),
  client_id VARCHAR(256)
  );
   
  create table oauth_access_token (
  token_id VARCHAR(256),
  token LONGVARBINARY,
  authentication_id VARCHAR(256) PRIMARY KEY,
  user_name VARCHAR(256),
  client_id VARCHAR(256),
  authentication LONGVARBINARY,
  refresh_token VARCHAR(256)
  );
   
  create table oauth_refresh_token (
  token_id VARCHAR(256),
  token LONGVARBINARY,
  authentication LONGVARBINARY
  );
   
  create table oauth_code (
  code VARCHAR(256), authentication LONGVARBINARY
  );
   
  create table oauth_approvals (
  userId VARCHAR(256),
  clientId VARCHAR(256),
  scope VARCHAR(256),
  status VARCHAR(10),
  expiresAt TIMESTAMP,
  lastModifiedAt TIMESTAMP
  );
   
   
  -- customized oauth_client_details table
  create table ClientDetails (
  appId VARCHAR(256) PRIMARY KEY,
  resourceIds VARCHAR(256),
  appSecret VARCHAR(256),
  scope VARCHAR(256),
  grantTypes VARCHAR(256),
  redirectUrl VARCHAR(256),
  authorities VARCHAR(256),
  access_token_validity INTEGER,
  refresh_token_validity INTEGER,
  additionalInformation VARCHAR(4096),
  autoApproveScopes VARCHAR(256)
  );
 
时间: 2024-12-12 15:54:28

【JavaEE】SSH+Spring Security+Spring oauth2环境方法及example的相关文章

使用Spring Security和OAuth2实现RESTful服务安全认证

这篇教程是展示如何设置一个OAuth2服务来保护REST资源. 源代码下载github. (https://github.com/iainporter/oauth2-provider)你能下载这个源码就开始编写一个被OAuth方法保护的服务.该源码包含功能: * 用户注册和登录* Email验证* Password 丢失 采取的技术有以下: * OAuth2 Protocol * spring Security * Spring Integration * Spring Data * Jerse

Spring Security实现OAuth2.0授权服务 - 进阶版

<Spring Security实现OAuth2.0授权服务 - 基础版>介绍了如何使用Spring Security实现OAuth2.0授权和资源保护,但是使用的都是Spring Security默认的登录页.授权页,client和token信息也是保存在内存中的. 本文将介绍如何在Spring Security OAuth项目中自定义登录页面.自定义授权页面.数据库配置client信息.数据库保存授权码和token令牌. 一.引入依赖 需要在基础版之上引入thymeleaf.JDBC.my

Spring Security 与 OAuth2(介绍)

https://www.jianshu.com/p/68f22f9a00ee Spring Security 与 OAuth2(介绍) 林塬 2018.01.23 11:14* 字数 3097 阅读 3660评论 1喜欢 6 个人 OAuth2 全部文章 Spring Security 与 OAuth2(介绍):https://www.jianshu.com/p/68f22f9a00ee Spring Security 与 OAuth2(授权服务器):https://www.jianshu.co

Spring Security 与 OAuth2 介绍

个人 OAuth2 全部文章 Spring Security 与 OAuth2(介绍):https://www.jianshu.com/p/68f22f9a00ee Spring Security 与 OAuth2(授权服务器):https://www.jianshu.com/p/227f7e7503cb Spring Security 与 OAuth2(资源服务器):https://www.jianshu.com/p/6dd03375224d Spring Security 与 OAuth2(

Spring Security: Spring Security简介

Spring Security简介 安全领域的两大核心是:Authentication和Authorization . ·Authentication是身份认证,把控一个系统的入口. ·Authorization是授权,用于进行系统中功能的访问控制. Spring Security 为J2EE项目提供了一个综合的解决方案,支持Authentication和Authorization. Spring Security对于Authentication提供了很宽泛的支持.集成了多种认证技术: HTTP

Spring Cloud之Oauth2环境搭建

oauth2 server 微服务授权中心 在Spring Cloud需要使用oauth2来实现多个微服务的统一认证授权,通过向OAUTH服务发送某个类型的grant type进行集中认证和授权,从而获得access_token,而这个token是受其他微服务信任的,我们在后续的访问可以通过access_token来进行,从而实现了微服务的统一认证授权.客户端根据约定的ClientID.ClientSecret.Scope来从Access Token URL地址获取AccessToken,并经过

Spring Security+Spring MVC+Mybatis

项目环境:JDK8+maven3.0+MySQL 项目结构: pom.xml: <?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation=&qu

spring security +spring boot 自定义 403 页面

用的spring security  做的权限控制, 当  访问没有权限, 跳转 会跳到默认403 页面.不符合当前项目需求. 一下是解决方式: package com.ycmedia; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.EnableAutoConfiguration; import org.springframework.boot.au

轻量级javaEE SSH 03: Spring

本系列的相关内容, 是这两年积累下来的, 本次整理成网页版本, 一方面共享给大家, 另一方面也方便自己查阅. 此部分介绍Spring 相关内容: part2: