概述
javaconfig版本: https://www.cnblogs.com/question-sky/p/7068511.html
以下使用的是SpringBoot 2.1.1进行测试
0 Maven引用
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<!-- 添加spring security cas支持 -->
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-cas</artifactId>
</dependency>
1 Springboot 启动类注解和配置扫描
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true) // 启用方法级别的权限认证
@ImportResource(locations={"classpath:spring/spring-security.xml"})
server.servlet.context-path=/b //设置项目的全局URL前缀(此处只是项目需求,与整合无关)
2 配置spring-security.xml
localhost:8080 为CAS认证服务器(认证服务器搭建 https://blog.csdn.net/shanchahua123456/article/details/85547516)
localhost:8787 为当前项目
<?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"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security.xsd">
<!-- http标签是 spring security 配置标签-->
<http pattern="/static/**" security="none"></http>
<http pattern="/css/**" security="none"></http>
<http pattern="/img/**" security="none"></http>
<http pattern="/js/**" security="none"></http>
<http pattern="/plugins/**" security="none"></http>
<!-- security 配置 use-expressions:是否启动SPEL表达式 默认是true -->
<!-- cas入口点引用 entry-point-ref是security框架接入第三方服务的通用入口 -->
<http use-expressions="true" entry-point-ref="casProcessingFilterEntryPoint">
<!-- security 配置 页面的拦截规则-->
<intercept-url pattern="/**" access="hasRole('ROLE_USER')"/>
<intercept-url pattern="/b/qq/**" access="hasRole('ROLE_USER') and hasIpAddress('10.10.10.3')" />
<csrf disabled="true"/>
<!-- html允许加载 同源iframe -->
<headers>
<frame-options policy="SAMEORIGIN"/>
</headers>
<!-- custom-filter为过滤器, position 表示将过滤器放在指定的位置上,before表示放在指定位置之前 ,after表示放在指定的位置之后 -->
<!-- 将CAS的过滤器 加入security框架-->
<custom-filter ref="casAuthenticationFilter" position="CAS_FILTER" />
<custom-filter ref="requestSingleLogoutFilter" before="LOGOUT_FILTER"/>
<custom-filter ref="singleLogoutFilter" before="CAS_FILTER"/>
</http>
<!-- CAS入口点 开始 -->
<!-- localhost:8080 为CAS认证服务器地址-->
<!-- localhost:8787 为本项目地址-->
<beans:bean id="casProcessingFilterEntryPoint" class="org.springframework.security.cas.web.CasAuthenticationEntryPoint">
<!-- 单点登录CAS服务器登录URL , localhost:8080 为CAS认证服务器,需要登录时会重定向到此URL上-->
<beans:property name="loginUrl" value="http://localhost:8080/cas/login"/>
<beans:property name="serviceProperties" ref="serviceProperties"/>
</beans:bean>
<!--设置客户端service的属性-->
<beans:bean id="serviceProperties" class="org.springframework.security.cas.ServiceProperties">
<!--设置回调的service路径 配置 自身工程的根地址+/login/cas 是固定写法。必须是此格式,不然会造成死循环,出现“重定向过多”错误-->
<!--注意:因为本项目设置了公共URL前缀server.servlet.context-path=/b,所以根地址为localhost:8787/b,否则根地址是localhost:8787 -->
<beans:property name="service" value="http://localhost:8787/b/login/cas"/>
</beans:bean>
<!-- CAS入口点 结束 -->
<!-- 认证过滤器 开始 -->
<beans:bean id="casAuthenticationFilter" class="org.springframework.security.cas.web.CasAuthenticationFilter">
<beans:property name="authenticationManager" ref="authenticationManager"/>
</beans:bean>
<!-- 认证管理器 -->
<authentication-manager alias="authenticationManager">
<authentication-provider ref="casAuthenticationProvider">
</authentication-provider>
</authentication-manager>
<!-- 认证提供者 -->
<beans:bean id="casAuthenticationProvider" class="org.springframework.security.cas.authentication.CasAuthenticationProvider">
<beans:property name="authenticationUserDetailsService">
<beans:bean class="org.springframework.security.core.userdetails.UserDetailsByNameServiceWrapper">
<beans:constructor-arg ref="userDetailsService" />
</beans:bean>
</beans:property>
<!--serviceProperties属性主要应用于ticketValidator用于去cas服务端检验ticket-->
<beans:property name="serviceProperties" ref="serviceProperties"/>
<!-- ticketValidator 为票据验证器 -->
<beans:property name="ticketValidator">
<beans:bean class="org.jasig.cas.client.validation.Cas20ServiceTicketValidator">
<!--localhost:8080 为CAS服务器 -->
<beans:constructor-arg index="0" value="http://localhost:8080/cas"/>
</beans:bean>
</beans:property>
<beans:property name="key" value="an_id_for_this_auth_provider_only"/>
</beans:bean>
<!-- 自定义授权类 其实现SpringSecurity的UserDetailsService接口,但是只负责授权。密码认证交给CAS服务器完成-->
<!-- 其在CAS认证之后 再执行授权 -->
<beans:bean id="userDetailsService" class="com.example.nginxtest.UserDetailServiceImpl"/>
<!-- 认证过滤器 结束 -->
<!-- 单点登出 开始 -->
<beans:bean id="singleLogoutFilter" class="org.jasig.cas.client.session.SingleSignOutFilter">
<!--CAS 3.5 以上版本 需要配以下属性 -->
<!--设置cas服务端路径前缀,应用于front channel的注销请求-->
<!--casServerUrlPrefix 与 cas服务器的配置文件相同WEB-INFcas.properties-->
<beans:property name="casServerUrlPrefix" value="https://localhost:8080/cas"></beans:property>
<beans:property name="ignoreInitConfiguration" value="true"></beans:property>
</beans:bean>
<!-- 经过以下配置,当用户在地址栏输入 本工程+/logout/cas即可登出 -->
<beans:bean id="requestSingleLogoutFilter" class="org.springframework.security.web.authentication.logout.LogoutFilter">
<!--CAS服务器登出URL service= 为登出后跳转URL-->
<beans:constructor-arg value="http://localhost:8080/cas/logout?service=http://www.baidu.com"/>
<beans:constructor-arg>
<beans:bean class="org.springframework.security.web.authentication.logout.SecurityContextLogoutHandler"/>
</beans:constructor-arg>
<!--配置本地工程登出地址 /logout/cas为自定义登出路径,cas框架自动与requestSingleLogoutFilter中的地址绑定-->
<beans:property name="filterProcessesUrl" value="/logout/cas"/>
</beans:bean>
<!-- 单点登出 结束 -->
</beans:beans>
4 Security角色权限认证。此处只为测试简单,真实环境需要注入DAO层查询权限。
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import java.util.ArrayList;
import java.util.List;
public class UserDetailServiceImpl implements UserDetailsService {
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
System.out.println("经过认证类:"+username);
List<GrantedAuthority> authorities=new ArrayList();
authorities.add(new SimpleGrantedAuthority("ROLE_USER"));
return new User(username,"",authorities);
}
}
5 NGINX配置
经测试使用浏览器通过NGINX访问两个配置了CAS登录的不同服务,可以实现SSO。
location /b {
proxy_pass http://192.168.1.55:8787;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Cookie $http_cookie;
}
location /a {
proxy_pass http://192.168.1.55:8788;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Cookie $http_cookie;
}
7 Security框架取得用户信息
方案一:SecurityContextHolder中获取
可以自定义实现UserDetails类
//获得当前登陆用户对应的对象
UserDetails userDetails = (UserDetails) SecurityContextHolder.getContext()
.getAuthentication()
.getPrincipal();
//获得当前登陆用户所拥有的所有权限
GrantedAuthority[] authorities = userDetails.getAuthorities();
String username= userDetails.getName();
方案二:Session中获取
SecurityContextImpl securityContextImpl = (SecurityContextImpl) request
.getSession().getAttribute("SPRING_SECURITY_CONTEXT");
// 登录名
securityContextImpl.getAuthentication().getName();
// 登录密码,未加密的
securityContextImpl.getAuthentication().getCredentials();
WebAuthenticationDetails details = (WebAuthenticationDetails) securityContextImpl
.getAuthentication().getDetails();
// 获得访问地址
details.getRemoteAddress();
// 获得sessionid
details.getSessionId();
// 获得当前用户所拥有的权限
List<GrantedAuthority> authorities = (List<GrantedAuthority>) securityContextImpl
.getAuthentication().getAuthorities();
for (GrantedAuthority grantedAuthority : authorities) {
System.out.println("Authority" + grantedAuthority.getAuthority());
}
8 CSRF+AJAX跨站伪造
上边配置是关闭CSRF。若开启的话,结合AJAX需要注意。
http://www.cnblogs.com/Joeee/p/7544573.html
https://www.cnblogs.com/zhufu9426/p/7814084.html
https://blog.csdn.net/starrrr2/article/details/50074445
html设置:全局index页面设置即可, 不需要每个页面都写
<meta name="_csrf" content="${_csrf.token}" />
<meta name="_csrf_header" content="${_csrf.headerName}" />
ajax 请求:
var token = $("meta[name='_csrf']").attr("content");
var header = $("meta[name='_csrf_header']").attr("content");
$.ajax({
url: "./deleteRes",
method: 'post',
dataType: 'json',
data: {
resIds: str,
},
beforeSend: function(request) {
request.setRequestHeader(header, token);
},
success: function(resp) {
}
});
最后
以上就是灵巧唇彩为你收集整理的Nginx+Springboot+Security+CAS 整合方案-XML 实现SSO客户端的全部内容,希望文章能够帮你解决Nginx+Springboot+Security+CAS 整合方案-XML 实现SSO客户端所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复