本人自己 研究及综合部分网上资料,整理得出,欢迎批评指正,欢迎一起探讨:
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
本篇将深入探讨如何利用Spring Cloud集成OAuth2来实现身份认证和单点登录(Single Sign-On,简称SSO)。 OAuth2是一种授权框架,它允许第三方应用获取资源所有者的特定资源,同时保护了资源所有者的隐私信息。在...
在实现集成登录认证组件时,我们需要了解OAuth2.0认证体系、SpringBoot、SpringSecurity以及Spring Cloud等相关知识。同时,我们还需要了解如何定义拦截器、如何在拦截的通知进行预处理、如何在UserDetailService....
总的来说,实现Spring Security、Spring OAuth2和Spring MVC的SSO单点登录系统,需要对这些框架有深入理解,并正确配置相应的jar包或Maven/Gradle依赖。通过这个最小化集合,开发者可以快速搭建SSO环境,然后根据...
基于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是两个在Web应用安全领域广泛应用的框架,它们结合使用可以构建强大的单点登录(SSO)和认证授权系统。在这个系统中,`xp-sso-server`代表了认证服务器,而`xp-sso-client-a`和`xp-sso-...
使用Spring Security OAuth2实现单点登录 概述: 在本教程中,我们将讨论如何使用Spring Security OAuth和Spring Boot实现单点登录(SSO)。单点登录是一种身份验证机制,允许用户使用一个身份验证凭证访问多个相关...
在Web服务中,OAuth2常用于实现单点登录(SSO,Single Sign-On)和API访问控制,确保数据安全的同时提供便捷的用户体验。 在这个完整的demo中,开发者已经构建了一个使用Spring Boot、Spring Security和OAuth2的...
在本案例中,我们将探讨如何利用Spring Security OAuth2实现SSO(Single Sign-On)单点登录功能。 SSO是一种让用户只需一次登录就能够访问多个相互信任的应用系统的技术。在企业环境中,这种功能能够极大地提高用户...
如描述中提到,Spring Security OAuth项目已被逐步弃用,取而代之的是Spring Security 5.x中的OAuth2支持。因此,应当选择Spring Security的核心模块,而不是单独的Spring Security OAuth依赖。 3. **利用Spring ...
springboot2.0+oauth搭建的SSO单点登录的源码,仅仅实现登录功能,无需积分即可下载,如有问题请留言
此外,笔记中可能还涉及了Spring Security与OAuth2.0结合时的常见问题和最佳实践,例如如何处理刷新令牌以延长访问权限,如何实现单点登录(SSO),以及如何利用JWT(JSON Web Tokens)来提高性能和安全性。...
开发人员可以通过配置Spring Security的OAuth2模块来保护REST API、实现单点登录(SSO)或者让第三方应用接入。 3. **spring-security-oauth2-2.0.3.RELEASE-sources.jar**:这是源码JAR文件,包含Spring Security ...
SSO(Single Sign-On)单点登录是一种身份验证机制,允许用户在一次登录后访问多个相互关联的应用系统,而无需再次进行身份验证。在本项目中,通过集成Spring Security OAuth2和JWT(JSON Web Token)技术,实现了...
在"spring-cloud-examples-master"这个压缩包中,可能包含了示例代码和配置文件,用于演示如何在Spring Cloud环境中集成OAuth2和Zuul实现单点登录。你可以通过阅读源码,理解它们的配置和交互方式,进一步了解如何在...
在当今的互联网应用中,单点登录(Single Sign-On,简称SSO)已经成为一种常见的身份验证机制,它允许用户在一个系统中登录后,无需再次登录就能访问其他关联系统。在本项目中,我们将深入探讨如何利用Spring ...