快捷搜索:  汽车  科技

使用spring实现单点登录(SpringSecurityCAS)

使用spring实现单点登录(SpringSecurityCAS)默认用户名和密码在cas\WEB-INF\classes\application.properties中 用户名:casuser 密码:Mellon把war包放在tomcat中启动下载官方的cas-overlay-template,在此基础上修改打包,运行。 cas-overlay-template已经集成了springboot,可直接运行。build之后会在target目录生成一个cas.war文件编译过程需要下载很多文件,过程有点长,需要耐心等待 如果本机maven环境变量没配置,用idea打开工程编译也可以

版本说明

6.0及以上需要jdk11,如果你是jdk8,最高只能用5.3版本

5.3以下版本的是maven工程,6.0以上改成gradle工程了

这里基于5.3版本搭建

原理

使用spring实现单点登录(SpringSecurityCAS)(1)

一、服务端搭建1、下载源码

HTTPS://github.com/apereo/Cas-overlay-template/tree/5.3

下载官方的cas-overlay-template,在此基础上修改打包,运行。 cas-overlay-template已经集成了springboot,可直接运行。

build之后会在target目录生成一个cas.war文件

编译过程需要下载很多文件,过程有点长,需要耐心等待 如果本机maven环境变量没配置,用idea打开工程编译也可以

把war包放在tomcat中启动

默认用户名和密码在cas\WEB-INF\classes\application.properties中 用户名:casuser 密码:Mellon

CAS默认使用的是HTTPS协议,如果使用HTTPS协议需要SSL安全证书(需向特定的机构申请和购买) 。如果对安全要求不高或是在开发测试阶段,可使用HTTP协议。我们这里讲解通过修改配置,让CAS使用HTTP协议。 如果不去除https认证下面整合客户端时会出现未认证授权的服务

2、去掉https配置

使用http链接跳转到cas服务器默认会有未认证授权的服务提示

使用spring实现单点登录(SpringSecurityCAS)(2)

1)修改CAS服务端配置文件 cas\WEB-INF\classes目录的application properties添加如下的内容

cas.tgc.secure=false cas.serviceRegistry.initFromJson=true

2)cas\WEB-INF\classes\services目录下的HTTPSandIMAPS-10000001.json 修改内容如下 即添加http "serviceId" : "^(https|http|imaps)://.*"

3)重启tomcat

3、tomcat 配置https证书

1、生成证书

keytool -genkey -alias sso-server -keystore ./mydestore -keyalg RSA -validity 2000 -storepass 111111 -keypass 111111 # 输入:sso-server.com keytool -export -alias sso-server -keystore ./mydestore -file server.crt -keypass 111111 # 将证书导入到jdk keytool -import -alias sso-server -File ./server.crt -keystore "C:/Program Files/Java/jdk1.8.0_161/jre/lib/security/cacerts" -storepass changeit -keypass 111111 # jdk默认密码:changeit

2、配置tomcat

把证书文件mydestore复制到conf目录下

<Connector port="8443" Protocol="org.apache.coyote.http11.Http11NioProtocol" maxThreads="150" SSLEnabled="true" scheme="https" secure="true" clientAuth="false" sslProtocol="TLS" keystoreFile="conf/mydestore" keystorePass="111111" > </Connector>

修改本地host文件:

127.0.0.1 sso-server.com

重启tomcat,输入访问地址:https://sso-server.com:8443/cas

4、修改cas-server链接到mysql数据库

1)服务端工程引入jar包,重新编译生成cas.war

<dependency> <groupId>org.apereo.cas</groupId> <artifactId>cas-server-support-jdbc</artifactId> <version>${cas.version}</version> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>8.0.13</version> </dependency>

2)修改配置文件: cas/WEB-INF/classes/application.properties

## # CAS Authentication Credentials # # cas.authn.accept.users=casuser::Mellon cas.authn.jdbc.query[0].url=jdbc:mysql://127.0.0.1:3306/user?serverTimezone=GMT+8&useUnicode=true&characterEncoding=UTF-8&useSSL=false&allowPublicKeyRetrieval=true cas.authn.jdbc.query[0].user=root cas.authn.jdbc.query[0].password=password cas.authn.jdbc.query[0].sql=select * from u_user where nickname = ? cas.authn.jdbc.query[0].fieldPassword=pswd cas.authn.jdbc.query[0].driverClass=com.mysql.cj.jdbc.Driver ## md5加密 cas.authn.jdbc.query[0].passwordEncoder.type=DEFAULT cas.authn.jdbc.query[0].passwordEncoder.characterEncoding=UTF-8 cas.authn.jdbc.query[0].passwordEncoder.encodingAlgorithm=MD5 #配置单点登出 #配置允许登出后跳转到指定页面 cas.logout.followServiceRedirects=true #跳转到指定页面需要的参数名为 service cas.logout.redirectParameter=service #登出后需要跳转到的地址 如果配置该参数 service将无效。 # cas.logout.redirectUrl=http://sso-server.com:8088/index #在退出时是否需要 确认退出提示 true弹出确认提示框 false直接退出 cas.logout.confirmLogout=true #是否移除子系统的票据 cas.logout.removeDescendantTickets=true #禁用单点登出 默认是false不禁止 #cas.slo.disabled=true #默认异步通知客户端 清除session #cas.slo.asynchronous=true

3)测试数据库脚本

CREATE TABLE `u_user` ( `id` bigint(20) NOT NULL AUTO_INCREMENT `nickname` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '用户昵称' `email` varchar(128) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '邮箱|登录帐号' `pswd` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '密码' `create_time` datetime(0) NULL DEFAULT NULL COMMENT '创建时间' `last_login_time` datetime(0) NULL DEFAULT NULL COMMENT '最后登录时间' `status` bigint(1) NULL DEFAULT 1 COMMENT '1:有效,0:禁止登录' PRIMARY KEY (`id`) USING BTREE ) ENGINE = InnoDB AUTO_INCREMENT = 15 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci ROW_FORMAT = Dynamic; INSERT INTO `u_user` VALUES (1 'admin' 'admin@163.com' md5('1') NOW() NULL 1);

4)将war包copy到tomcat运行

二、客户端配置,配置cas-client(集成Spring-security)

客户端就是自己的项目工程

1、引入jar包

<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-security</artifactId> </dependency> <dependency> <groupId>org.springframework.security</groupId> <artifactId>spring-security-cas</artifactId> </dependency> 2、添加配置项

#cas服务端的地址 cas.server-url-prefix=http://localhost:8080/cas #cas服务端的登录地址 cas.server-login-url=http://localhost:8080/cas/login #当前服务器的地址(客户端) cas.client-host-url=http://localhost:8088 3、代码示例

启动类添加注解

@SpringBootApplication //开启spring security过滤器链 @EnableWebSecurity public class CasDemoClientApplication { public static void main(String[] args) { SpringApplication.run(CasDemoClientApplication.class args); } }

CAS配置类

package com.example.casclient.config; import com.example.casclient.security.CustomUserDetailsService; import org.jasig.cas.client.session.SingleSignOutFilter; import org.jasig.cas.client.validation.Cas30ServiceTicketValidator; import org.jasig.cas.client.validation.TicketValidator; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.security.authentication.AuthenticationManager; import org.springframework.security.authentication.ProviderManager; import org.springframework.security.cas.ServiceProperties; import org.springframework.security.cas.authentication.CasAuthenticationProvider; import org.springframework.security.cas.web.CasAuthenticationEntryPoint; import org.springframework.security.cas.web.CasAuthenticationFilter; import org.springframework.security.web.AuthenticationEntryPoint; import org.springframework.security.web.authentication.logout.LogoutFilter; import org.springframework.security.web.authentication.logout.SecurityContextLogoutHandler; @Configuration public class CasConfig { @Value("${cas.server-url-prefix}") private String casServerUrl; @Value("${cas.client-host-url}") private String baseUrl; @Bean public AuthenticationEntryPoint authenticationEntryPoint() { CasAuthenticationEntryPoint entryPoint = new CasAuthenticationEntryPoint(); entryPoint.setLoginUrl(casServerUrl "/login"); entryPoint.setServiceProperties(this.serviceProperties()); return entryPoint; } @Bean protected AuthenticationManager authenticationManager() throws Exception { return new ProviderManager(this.casAuthenticationProvider()); } @Bean public CasAuthenticationFilter casAuthenticationFilter( AuthenticationManager authenticationManager ServiceProperties serviceProperties) throws Exception { CasAuthenticationFilter filter = new CasAuthenticationFilter(); filter.setAuthenticationManager(authenticationManager); filter.setServiceProperties(serviceProperties); return filter; } @Bean public ServiceProperties serviceProperties() { ServiceProperties serviceProperties = new ServiceProperties(); serviceProperties.setService(baseUrl "/login/cas"); serviceProperties.setSendRenew(false); return serviceProperties; } @Bean public TicketValidator ticketValidator() { return new Cas30ServiceTicketValidator(casServerUrl); } @Bean public CasAuthenticationProvider casAuthenticationProvider() { CasAuthenticationProvider provider = new CasAuthenticationProvider(); provider.setServiceProperties(this.serviceProperties()); provider.setTicketValidator(this.ticketValidator()); provider.setUserDetailsService(new CustomUserDetailsService()); provider.setKey("CAS_PROVIDER_LOCALHOST"); return provider; } @Bean public SecurityContextLogoutHandler securityContextLogoutHandler() { return new SecurityContextLogoutHandler(); } @Bean public LogoutFilter logoutFilter() { LogoutFilter logoutFilter = new LogoutFilter(casServerUrl "/logout?service=" baseUrl securityContextLogoutHandler()); logoutFilter.setFilterProcessesUrl("/logout/cas"); return logoutFilter; } @Bean public SingleSignOutFilter singleSignOutFilter() { SingleSignOutFilter singleSignOutFilter = new SingleSignOutFilter(); singleSignOutFilter.setIgnoreInitConfiguration(true); return singleSignOutFilter; } }

WebConfig配置类

package com.example.casclient.config; import org.jasig.cas.client.session.SingleSignOutFilter; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.security.cas.web.CasAuthenticationFilter; import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; import org.springframework.security.web.AuthenticationEntryPoint; import org.springframework.security.web.authentication.logout.LogoutFilter; @EnableWebSecurity public class WebConfig extends WebSecurityConfigurerAdapter { @Autowired private SingleSignOutFilter singleSignOutFilter; @Autowired private LogoutFilter logoutFilter; @Autowired private AuthenticationEntryPoint authenticationEntryPoint; @Autowired private CasAuthenticationFilter casAuthenticationFilter; @Override protected void configure(HttpSecurity http) throws Exception { http.authorizeRequests() .antMatchers("/login/cas").permitAll() .anyRequest().authenticated() .and().httpBasic().authenticationEntryPoint(authenticationEntryPoint) .and() .addFilter(casAuthenticationFilter) .addFilterBefore(singleSignOutFilter CasAuthenticationFilter.class) .addFilterBefore(logoutFilter LogoutFilter.class); } }

授权后获取用户信息处理类

package com.example.casclient.security; import org.springframework.security.core.authority.AuthorityUtils; 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; public class CustomUserDetailsService implements UserDetailsService { @Override public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException { // 可自定义获取用户信息 // 示例代码写死,实际应该从数据库获取用户信息,并加载对应的权限 return new User(username username true true true true AuthorityUtils.createAuthorityList("ROLE_ADMIN")); } }

添加测试Controller类

package com.example.casclient.controller; import org.springframework.security.core.Authentication; import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.security.core.userdetails.User; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.web.bind.annotation.RequestMapping; import javax.servlet.http.HttpSession; @Controller public class IndexController { @RequestMapping(value = "") public String index(Model model) { Authentication auth = SecurityContextHolder.getContext().getAuthentication(); User user = (User) auth.getPrincipal(); System.out.println("当前用户信息:" user); model.addAttribute("user" user); return "index"; } @RequestMapping(value = "info") public String info(Model model) { return "info"; } }

测试页面代码,templates/index.html

<!DOCTYPE html> <html xmlns:th="http://www.thymeleaf.org" xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout"> <head> <meta charset="UTF-8"> <title>首页</title> </head> <body class="home-body"> <h1>首页信息</h1> <div>登录用户信息</div> <div>用户名:<span th:text="${user.username}"></span></div> </body> </html> 三、测试

1)在浏览中输入地址(http://sso-server.com:8088)会跳转到cas登录页面

输入指定的用户名/密码:admin/1

使用spring实现单点登录(SpringSecurityCAS)(3)

2)登录成功跳转到页面

使用spring实现单点登录(SpringSecurityCAS)(4)

3)注销,输入地址:http://sso-server.com:8088/logout/cas,点击确认退出,页面会回到登录页面

使用spring实现单点登录(SpringSecurityCAS)(5)

或直接在cas服务端退出:https://sso-server.com:8443/cas/logout

使用spring实现单点登录(SpringSecurityCAS)(6)

参考地址
  • https://github.com/apereo/cas
  • https://github.com/apereo/cas-overlay-template
  • https://www.apereo.org/projects/cas
  • https://github.com/apereo/java-cas-client
  • https://apereo.github.io/cas/5.3.x/installation/Configuration-Properties.html#query-database-authentication

猜您喜欢: