本人自己 研究及综合部分网上资料,整理得出,欢迎批评指正,欢迎一起探讨:
1.jar版本:
jdk1.6、spring3.1.1、spring-security3.1.0、spring-security-oauth2-1.0.5
2.背景:
客户公司 已经存在的N个系统,且每个系统用户名会有不一致情况,用户使用系统时需要多个系统协同操作,弊端凸显。为此,需要一个统一认证中心。
3.前提:
3.1:以上N个系统的用户是统一一个出处,如:一个AD域、数据库、LDAP等
3.2:app接入OAuth2的AuthorizationCode方式(其他方式本人未调试过)
3.3:OAuth的5个表已经生成到中心数据库中,并与中心app注册功能整合在一起。
4.定义:
4.1AbstractDomain.java:其中guid默认赋值为uuid,该类覆盖equals、hashCode,guid用户标识用户对象
的创建的唯一性,即同一用户在不同客户端登陆后,用户对象不同。
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (!(o instanceof AbstractDomain)) {
return false;
}
AbstractDomain that = (AbstractDomain) o;
return guid.equals(that.guid);
}
@Override
public int hashCode() {
return guid.hashCode();
}
4.2用户对象User.java:继承AbstractDomain,是中心的用户对象,也是OAuth接口获取用户信息的bean。
5.思路:
使用cookie缓存用户登录信息,app向中心登录时,获取该cookie,同时验证中心的session中是否存在该用户,存在则执行单点登录。
认证中心为一个CAS服务,同时需要app向中心注册,并提供appCode及redirectUrl,便于OAuth认证时调用。客户端登陆成功后,中心会向客户端浏览器写入cookie,保存登陆用户信息,作为单点登录凭据,用户关闭浏览器时,cookie自动失效。
6.典型场景:
6.1:用户在浏览器上输入app地址,app过滤器验证未登录后,附上appCode,然后发起OAuth第一步认证请求,中心过滤器判断用户是否登录,
6.1.1未登录:则会跳转到登陆页面,用户填写用户名密码进行登录,中心获取到登录成功后(向客户端写
入cookie),会继续执行OAuth认证,此时会弹出用户授权页面,当用户点击授权按钮后,转6.1.3
6.1.2已登录:转到授权页面(如果之前已经授权,会继续往下走),转6.1.3
6.1.3中心获取到授权后生成授权码,然后跳转到app的redirectUrl,app获取到授权码,根据授权码继续发送认证第二步请求,以授权码换取token,获取到token后,根据token访问中心提供的用户接口获取用户信息(json),app使用用户信息构建app的session、权限等数据,之后做具体业务操作,认证完成。
6.2:用户在该浏览器地址栏再输入app2的地址时,app2也发起OAuth第一步认证,中心仍然跳转到登陆页,此时登陆页获取cookie中用户名与guid信息,自动提交登录信息到action中验证session中是否存在该用户,不存在则调整到登录页面,存在则跳转到app2的redirectUrl,继续向下执行6.1.2操作,以完成认证。
7.数据流程图:
8.代码:纯干货
8.1web.xml:
认证中心过滤器,放过一些请求
<filter>
<filter-name>loginFilter</filter-name>
<filter-class>*.util.LoginFilter</filter-class>
<init-param>
<param-name>AllowRes</param-name>
<param-value>
/login.do;/login.jsp;css;jpg;gif;png;bmp;jpeg;swf;ico;/demo/*;
/authTypeList.do;/authFail.do; /oauth/authorize;/oauth/token;/oauth/user_info.do;
isAgainAuth4Client.do
</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>loginFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
过滤器代理
<filter>
<filter-name>springSecurityFilterChain</filter-name>
<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
</filter>
<filter-mapping>
<filter-name>springSecurityFilterChain</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
额外添加spring session监听,用来处理在线用户
<listener>
<listener-class>org.springframework.security.web.session.HttpSessionEventPublisher</listener-class>
</listener>
8.2security.xml配置
<?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-3.1.xsd
http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-3.1.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/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.1.xsd">
<mvc:annotation-driven/>
<mvc:default-servlet-handler/>
<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>
<!--unity http configuration-->
<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 auto-config="true" access-denied-page="/ac/login/authFail.do?flag=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 login-processing-url="/login.do" login-page="/ac/portal/login1.jsp" default-target-url="/portal.do"
authentication-failure-url="/ac/login/authFail.do"/>
<logout logout-success-url="/ac/portal/login1.jsp?flag=out" logout-url="/logout.do"/>
<anonymous />
<custom-filter position="CONCURRENT_SESSION_FILTER" ref="concurrencyFilter" />
<session-management session-authentication-strategy-ref="sessionStrategy"/>
</http>
<beans:bean id="clientCredentialsTokenEndpointFilter"
class="org.springframework.security.oauth2.provider.client.ClientCredentialsTokenEndpointFilter">
<beans:property name="authenticationManager" ref="oauth2AuthenticationManager"/>
</beans:bean>
<!--unity resource server filter-->
<oauth2:resource-server id="unityResourceServer" resource-id="unity-resource" token-services-ref="tokenServices"/>
<beans:bean id="clientDetailsService" class="com.free.ac.oauth.common.CustomJdbcClientDetailsService">
<beans:constructor-arg index="0" ref="dataSource"/>
</beans:bean>
<!--Config token services-->
<beans:bean id="tokenStore" class="org.springframework.security.oauth2.provider.token.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"/>
</beans:bean>
<beans:bean id="oauthUserApprovalHandler" class="com.free.ac.oauth.common.OauthUserApprovalHandler">
<beans:property name="tokenServices" ref="tokenServices"/>
<beans:property name="oauthService" ref="oauthService"/>
</beans:bean>
<beans:bean id="jdbcAuthorizationCodeServices" class="org.springframework.security.oauth2.provider.code.JdbcAuthorizationCodeServices">
<beans:constructor-arg index="0" ref="dataSource"/>
</beans:bean>
<oauth2:authorization-server client-details-service-ref="clientDetailsService" token-services-ref="tokenServices"
user-approval-handler-ref="oauthUserApprovalHandler" user-approval-page="ac/portal/oauth_approval.jsp" error-page="ac/portal/oauth_error.jsp">
<oauth2:authorization-code authorization-code-services-ref="jdbcAuthorizationCodeServices"/>
<oauth2:implicit/>
<oauth2:refresh-token/>
<oauth2:client-credentials/>
<oauth2:password/>
</oauth2:authorization-server>
<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"/>
<authentication-manager alias="authenticationManager">
<authentication-provider user-service-ref="acUserDetailsService">
<password-encoder hash="md5"/>
</authentication-provider>
</authentication-manager>
<!-- session管理配置 -->
<beans:bean id="concurrencyFilter" class="org.springframework.security.web.session.ConcurrentSessionFilter">
<beans:property name="sessionRegistry" ref="sessionRegistry" />
</beans:bean>
<beans:bean id="sessionRegistry" class="org.springframework.security.core.session.SessionRegistryImpl" />
<beans:bean id="sessionStrategy" class="org.springframework.security.web.authentication.session.ConcurrentSessionControlStrategy">
<beans:property name="maximumSessions" value="1"></beans:property>
<beans:property name="exceptionIfMaximumExceeded" value="false"></beans:property>
<beans:constructor-arg name="sessionRegistry" ref="sessionRegistry"></beans:constructor-arg>
</beans:bean>
</beans:beans>
说明:
oauth2AccessDeniedHandler:自己编写的类,继承TokenServicesUserApprovalHandler,处理是否需要授权。
CustomJdbcClientDetailsService:自定义类,继承JdbcClientDetailsService,处理认证客户端
oauth_approval.jsp:授权成功页
oauth_error.jsp:授权失败页
acUserDetailsService:继承UserDetailsService,是中心提供的用户API接口
相关推荐
spring security 基于oauth 2.0 实现 sso 单点登录Demo 使用 spring security 基于oauth 2.0 实现 sso 单点登录Demo spring boot + spring security + spring security oauth
基于JWT OAUTH2 SpringSecurity单点登录 . 单点登录流: 1. 访问client1 2. `client1`将请求导向`sso-server` 3. 同意授权 4. 携带授权码`code`返回`client1` 5. `client1`拿着授权码请求令牌 6. 返回`JWT`令牌 7. ...
该资源是springsecurity+oauth2+jwt实现的单点登录demo,模式为授权码模式,实现自定义登录页面和自定义授权页面。应用数据存在内存中或者存在数据库中(附带数据库表结构),token存储分为数据库或者Redis。demo...
spring security + oauth 2.0 实现单点登录、认证授权,直接贴代码
基于spring security oauth2 实现的SSO单点登录案例,本案例非常完整,值得用于参考学习spring security oauth2
springboot2.0+oauth搭建的SSO单点登录的源码,仅仅实现登录功能,无需积分即可下载,如有问题请留言
在本教程中,我们将讨论如何使用Spring Security OAuth和Spring Boot实现SSO - 单点登录。感兴趣的朋友跟随小编一起看看吧
Spring Cloud 安全:集成OAuth2实现身份认证和单点登录 示例代码
实现功能需要的最小jar集合,其中lib文件夹是导出的jar,maven pom文件夹是maven组织的pom.xml文件。二选一。
主要介绍了Spring Security OAuth过期的解决方法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
该资源实现了一个sso单点登陆的功能,类似于在淘宝网登陆之后可以不需要登陆天猫即可访问天猫网;使用了spring security oauth2以及jwt。
以及spring security oauth2基于数据库的代码配置实现
使用 spring security 基于oauth 2.0 实现 sso 单点登录Demo spring boot + spring security + spring security oauth
该资源实现了一个sso单点登陆的功能,类似于在淘宝网登陆之后可以不需要登陆天猫即可访问天猫网;使用了spring security oauth2以及jwt。
Spring Security OAuth2单点登录 四、Spring Cloud教程 初识Spring Cloud与微服务 Spring Cloud Eureka服务治理 Spring Cloud Ribbon客户端负载均衡 Spring Cloud Hystrix服务容错 Spring Cloud Hystrix Dashboard...
SSO也就是单点登录,最重要的俩个功能:颁发token用户通过客户端访问应用系统,中间会先去访问授权服务器(SSO),SSO会颁发一个token返回给客户端;说
spring-security-sso简单的单点登录Spring Security OAuth21.概述在本教程中,我们将讨论如何使用Spring Security OAuth和Spring Boot实现单点登录 - 单点登录。我们将使用三个独立的应用程序授权服务器 - 这是中央...