springboot集成cas

相信许多小伙伴在开发过程中都需要使用单点登录,今天我就讲一讲我在公司的项目中集成的cas服务

那么首先 ,我们需要知道sso 及 cas

SSO

SSO 是英文 Single Sign On 的缩写,翻译过来就是单点登录。顾名思义,它把两个及以上个产品中的用户登录逻辑抽离出来,达到只输入一次用户名密码,就能同时登录多个产品的效果。

打个比方,SSO 和我们去迪士尼玩时购买的通票很像。

我们只要买一次通票,就可以玩所有游乐场内的设施,而不需要在过山车或者摩天轮那里重新买一次票。在这里,买票就相当于登录认证,游乐场就相当于使用一套 SSO 的公司,各种游乐设施就相当于公司的各个产品。

使用 SSO 的优点很明显:

  • 提升用户体验。

就以我厂为例。我厂有两个产品,丁香人才网和丁香园论坛,假如你是我厂用户,肯定无法忍受登录丁香园论坛的时候输入一次用户名密码,登录人才网又要输入一次用户名密码吧?

  • 避免重复开发

假如你是我厂后端,每天任务都饱和的不行,肯定无法忍受到人才网开发一套登录逻辑,到论坛又开发一套登录逻辑吧?

  • 提升安全系数

假如你是我厂运维,发现了一个安全隐患需要紧急修复。你肯定无法忍受给茫茫多的产品后端都发一封邮件,责令修复吧?万一漏了一个呢?

综合看来,SSO 不仅是有用的,而且是必要的。

CAS

SSO 仅仅是一种架构,一种设计,而 CAS 则是实现 SSO 的一种手段。两者是抽象与具体的关系。当然,除了 CAS 之外,实现 SSO 还有其他手段,比如简单的 cookie。

CAS (Central Authentication Service)中心授权服务,本身是一个开源协议,分为 1.0 版本和 2.0 版本。1.0 称为基础模式,2.0称为代理模式,适用于存在非 Web 应用之间的单点登录。

了解了以上信息 ,下面我们具体讲接一下,如何在springboot中集成cas

SSO单点登录访问流程主要有以下步骤:

  • 访问服务:SSO客户端发送请求访问应用系统提供的服务资源。
  • 定向认证:SSO客户端会重定向用户请求到SSO服务器。
  • 用户认证:用户身份认证。
  • 发放票据:SSO服务器会产生一个随机的Service Ticket。
  • 验证票据:SSO服务器验证票据Service Ticket的合法性,验证通过后,允许客户端访问服务。
  • 传输用户信息:SSO服务器验证票据通过后,传输用户认证结果信息给客户端。


(作者补充:其实简单来说,cas就是中央认证服务,就是单点登录,单点登录简称为sso!)

cas服务端部署

地址:https://github.com/apereo/cas-overlay-template/tree/5.3
1、解压下载的zip压缩包
2、解压后使用maven命令打包

mvn package 

3、把target下生成的war包重命名为cas.war放到tomcat下
4、启动tomcat
5、找到解压的文件

由于cas默认使用的是基于https协议,需要改为兼容使用http协议,打开对应你的目录文件:

D:\tomcat8\webapps\cas\WEB-INF\classes\application.properties

修改application.properties文件,添加下面配置,使用http

1

2

3

4

5

6

#使用http协议

cas.tgc.secure=false

cas.serviceRegistry.initFromJson=true

#由于https协议默认使用的端口为8443,还需我们修改为tomcat的8080端口

server.port=8080

修改HTTPSandIMAPS-10000001.json文件

D:\tomcat8\webapps\cas\WEB-INF\classes\services目录下的HTTPSandIMAPS-10000001.json

把原来的serviceId内容改成如下

"serviceId" : "^(https|http|imaps)://.*",

兼容http修改完毕。

修改配置中的登录用户名密码

cas.authn.accept.users=yyh::123456

cas服务器端搭建完毕,重启tomcat 进行测试,在浏览器中输入下面地址,进行访问

http://localhost:8080/cas/login

服务端就已经搭好了,并且可以通过登录退出了。

cas客户端搭建

在新建的springboot项目的pom.xml添加如下依赖(匹配对应的版本)

1

2

3

4

5

<dependency>

    <groupId>net.unicon.cas</groupId>

    <artifactId>cas-client-autoconfig-support</artifactId>

    <version>2.3.0-GA</version>

</dependency>

在resources下新建application.properties

1

2

3

4

5

6

7

8

9

server.port=8088

#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:8081

#Ticket校验器使用Cas30ProxyReceivingTicketValidationFilter

cas.validation-type=cas3

Application启动类上添加注解

1

2

3

4

5

6

7

8

9

10

11

12

13

import net.unicon.cas.client.configuration.EnableCasClient;

import org.springframework.boot.SpringApplication;

import org.springframework.boot.autoconfigure.SpringBootApplication;

//启用cas

@EnableCasClient

@SpringBootApplication

public class CasClient2Application {

    public static void main(String[] args) {

        SpringApplication.run(CasClient2Application.class, args);

    }

}

第一个客户端的controller

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

import org.jasig.cas.client.authentication.AttributePrincipal;

import org.jasig.cas.client.validation.Assertion;

import org.springframework.web.bind.annotation.RequestMapping;

import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpSession;

import static org.jasig.cas.client.util.AbstractCasFilter.CONST_CAS_ASSERTION;

@RestController

public class controller {

    @RequestMapping("/sso-test1")

    public String test1(HttpSession session){

        Assertion assertion = (Assertion)session.getAttribute(CONST_CAS_ASSERTION);

        AttributePrincipal principal = assertion.getPrincipal();

        String loginName = principal.getName();

        return "sso-test1,当前登录账户"+loginName;

    }

}

一个客户端就添加好了,添加另一个客户端出端口其他基本也是一样

第二个客户端的controller

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

import org.jasig.cas.client.authentication.AttributePrincipal;

import org.jasig.cas.client.validation.Assertion;

import org.springframework.boot.autoconfigure.EnableAutoConfiguration;

import org.springframework.web.bind.annotation.RequestMapping;

import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpSession;

import static org.jasig.cas.client.util.AbstractCasFilter.CONST_CAS_ASSERTION;

@RestController

public class controller {

    @RequestMapping("/sso-test2")

    public String test1(HttpSession session){

        Assertion assertion = (Assertion)session.getAttribute(CONST_CAS_ASSERTION);

        AttributePrincipal principal = assertion.getPrincipal();

        String loginName = principal.getName();

        return "sso-test222222,当前登录账户"+loginName;

    }

}

效果

在没有登录的情况下访问 http://localhost:8081/sso-test1

uploading.4e448015.gif

正在上传…重新上传取消

直接跳到了登录界面,并且把回调地址也带上了

访问第二个客户端 http://localhost:8082/sso-test2

跟第一个也是一样,这次我们随便登录一个

登录后,执行了回调接口,刷新一下第一个客户端的地址

也登录成功了。

配置统一登出

添加登出接口controller

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

/**

 * 退出 后自动重定向自定义接口

 * @param request

 * @return

 */

@RequestMapping("/system/logout1")

public String logout1(HttpServletRequest request) {

    HttpSession session = request.getSession();

    session.invalidate();

    return "redirect:http://localhost:8080/cas/logout?service=http://localhost:8081/system/logoutSuccess";

}

/**

 * 退出成功页

 * @return

 */

@RequestMapping("/system/logoutSuccess")

@ResponseBody

public String logoutSuccess() {

    return "test1成功退出!";

}

设置cas认证中心允许重定向跳转

打开你的cas认证中心里的 application.properties 文件,添加如下配置

1

2

#退出登录后允许跳转

cas.logout.followServiceRedirects=true

新建config配置文件

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99

100

101

102

103

104

105

106

107

108

109

110

111

112

113

114

115

116

117

118

119

120

121

122

import org.jasig.cas.client.authentication.AuthenticationFilter;

import org.jasig.cas.client.session.SingleSignOutFilter;

import org.jasig.cas.client.session.SingleSignOutHttpSessionListener;

import org.jasig.cas.client.util.HttpServletRequestWrapperFilter;

import org.jasig.cas.client.validation.Cas30ProxyReceivingTicketValidationFilter;

import org.springframework.boot.web.servlet.FilterRegistrationBean;

import org.springframework.boot.web.servlet.ServletListenerRegistrationBean;

import org.springframework.context.annotation.Bean;

import org.springframework.context.annotation.Configuration;

import java.util.EventListener;

import java.util.HashMap;

import java.util.Map;

@Configuration

public class config {

    //cas认证服务中心地址

    private static final String CAS_SERVER_URL_PREFIX = "http://localhost:8080/cas/";

    //cas认证服务中心   系统登录地址

    private static final String CAS_SERVER_URL_LOGIN = "http://localhost:8080/cas/login";

    //你自己的客户端1的地址

    private static final String SERVER_NAME = "http://localhost:8081/";

    /**

     * description: 登录过滤器

     * @param: []

     * @return: org.springframework.boot.web.servlet.FilterRegistrationBean

     */

    @Bean

    public FilterRegistrationBean filterSingleRegistration() {

        FilterRegistrationBean registration = new FilterRegistrationBean();

        registration.setFilter(new SingleSignOutFilter());

        // 设定匹配的路径

        registration.addUrlPatterns("/*");

        Map<String,String> initParameters = new HashMap<String, String>();

        initParameters.put("casServerUrlPrefix", CAS_SERVER_URL_PREFIX);

        registration.setInitParameters(initParameters);

        // 设定加载的顺序

        registration.setOrder(1);

        return registration;

    }

    /**

     * description:过滤验证器

     *     * @param: []

     * @return: org.springframework.boot.web.servlet.FilterRegistrationBean

     */

    @Bean

    public FilterRegistrationBean filterValidationRegistration() {

        FilterRegistrationBean registration = new FilterRegistrationBean();

        registration.setFilter(new Cas30ProxyReceivingTicketValidationFilter());

        // 设定匹配的路径

        registration.addUrlPatterns("/*");

        Map<String,String>  initParameters = new HashMap<String, String>();

        initParameters.put("casServerUrlPrefix", CAS_SERVER_URL_PREFIX);

        initParameters.put("serverName", SERVER_NAME);

        initParameters.put("useSession", "true");

        registration.setInitParameters(initParameters);

        // 设定加载的顺序

        registration.setOrder(1);

        return registration;

    }

    /**

     * description:授权过滤器

     * @param: []

     * @return: org.springframework.boot.web.servlet.FilterRegistrationBean

     */

    @Bean

    public FilterRegistrationBean filterAuthenticationRegistration() {

        FilterRegistrationBean registration = new FilterRegistrationBean();

        registration.setFilter(new AuthenticationFilter());

        // 设定匹配的路径

        registration.addUrlPatterns("/*");

        Map<String,String>  initParameters = new HashMap<String, String>();

        initParameters.put("casServerLoginUrl", CAS_SERVER_URL_LOGIN);

        initParameters.put("serverName", SERVER_NAME);

        //设置忽略  退出登录不用登录

        initParameters.put("ignorePattern", "/system/*");

        registration.setInitParameters(initParameters);

        // 设定加载的顺序

        registration.setOrder(1);

        return registration;

    }

    /**

     * wraper过滤器

     * @return

     */

    @Bean

    public FilterRegistrationBean filterWrapperRegistration() {

        FilterRegistrationBean registration = new FilterRegistrationBean();

        registration.setFilter(new HttpServletRequestWrapperFilter());

        // 设定匹配的路径

        registration.addUrlPatterns("/*");

        // 设定加载的顺序

        registration.setOrder(1);

        return registration;

    }

    /**

     * 添加监听器

     * @return

     */

    @Bean

    public ServletListenerRegistrationBean<EventListener> singleSignOutListenerRegistration(){

        ServletListenerRegistrationBean<EventListener> registrationBean = new ServletListenerRegistrationBean<EventListener>();

        registrationBean.setListener(new SingleSignOutHttpSessionListener());

        registrationBean.setOrder(1);

        return registrationBean;

    }

}

客户端2跟客户端1的大似相同,这样就可以实现登出一个系统,所有系统全部登出。

 以上便是我在项目中接入客户端的过程,望对大家有用

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值