详解Spring Boot 集成Shiro和CAS

2025-05-29 0 84

请大家在看本文之前,先了解如下知识点:

1、Shiro 是什么?怎么用?

2、Cas 是什么?怎么用?

3、最好有spring基础

首先看一下下面这张图:

第一个流程是单纯使用Shiro的流程。

第二个流程是单纯使用Cas的流程。

第三个图是Shiro集成Cas后的流程。

详解Spring Boot 集成Shiro和CAS

PS:流程图急急忙忙画的,整体上应该没有什么问题,具体细节问题还请大家留言指正。

如果你只是打算用到你的Spring Boot项目中,那么看着如下配置完成便可。

如果你想进一步了解其中的细节,还是建议大家单独配置Shiro、单独配置Cas,看看官方相关文档。

Shiro在1.2版本开始提供了对cas的集成,按下面添加依赖到pom.xml中:

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16
<!--Apache Shiro所需的jar包 -->

<dependency>

<groupId>org.apache.shiro</groupId>

<artifactId>shiro-spring</artifactId>

<version>1.2.4</version>

</dependency>

<dependency>

<groupId>org.apache.shiro</groupId>

<artifactId>shiro-ehcache</artifactId>

<version>1.2.4</version>

</dependency>

<dependency>

<groupId>org.apache.shiro</groupId>

<artifactId>shiro-cas</artifactId>

<version>1.2.4</version>

</dependency>

shiro-cas 依赖 shiro-web,shiro-web 依赖 shiro-core,所以添加shiro-cas后shiro-web.jar和shiro-core.jar会自动被引用。
cas被shiro集成后,其原理就是shiro将casFilter加入到shiroFilter的filterChain中。

在SpringBoot工程中创建ShiroCasConfiguration.Java

?

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

123

124

125

126

127

128

129

130

131

132

133

134

135

136

137

138

139

140

141

142

143

144

145

146

147

148

149

150

151

152

153

154

155

156

157

158

159

160

161

162

163

164

165

166

167

168

169

170

171

172

173

174

175

176

177

178

179

180

181

182

183

184

185

186
package org.springboot.sample.config;

import java.util.HashMap;

import java.util.LinkedHashMap;

import java.util.Map;

import javax.servlet.Filter;

import org.apache.shiro.cache.ehcache.EhCacheManager;

import org.apache.shiro.cas.CasFilter;

import org.apache.shiro.cas.CasSubjectFactory;

import org.apache.shiro.spring.LifecycleBeanPostProcessor;

import org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor;

import org.apache.shiro.spring.web.ShiroFilterFactoryBean;

import org.apache.shiro.web.mgt.DefaultWebSecurityManager;

import org.slf4j.Logger;

import org.slf4j.LoggerFactory;

import org.springboot.sample.dao.IScoreDao;

import org.springboot.sample.security.MyShiroCasRealm;

import org.springboot.sample.service.StudentService;

import org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator;

import org.springframework.boot.context.embedded.FilterRegistrationBean;

import org.springframework.context.annotation.Bean;

import org.springframework.context.annotation.Configuration;

import org.springframework.web.filter.DelegatingFilterProxy;

/**

* Shiro集成Cas配置

*

* @author 单红宇(365384722)

* @create 2016年1月17日

*/

@Configuration

public class ShiroCasConfiguration {

private static final Logger logger = LoggerFactory.getLogger(ShiroCasConfiguration.class);

// CasServerUrlPrefix

public static final String casServerUrlPrefix = "https://localhost:8443/cas";

// Cas登录页面地址

public static final String casLoginUrl = casServerUrlPrefix + "/login";

// Cas登出页面地址

public static final String casLogoutUrl = casServerUrlPrefix + "/logout";

// 当前工程对外提供的服务地址

public static final String shiroServerUrlPrefix = "http://localhost:9090/myspringboot";

// casFilter UrlPattern

public static final String casFilterUrlPattern = "/shiro-cas";

// 登录地址

public static final String loginUrl = casLoginUrl + "?service=" + shiroServerUrlPrefix + casFilterUrlPattern;

@Bean

public EhCacheManager getEhCacheManager() {

EhCacheManager em = new EhCacheManager();

em.setCacheManagerConfigFile("classpath:ehcache-shiro.xml");

return em;

}

@Bean(name = "myShiroCasRealm")

public MyShiroCasRealm myShiroCasRealm(EhCacheManager cacheManager) {

MyShiroCasRealm realm = new MyShiroCasRealm();

realm.setCacheManager(cacheManager);

return realm;

}

/**

* 注册DelegatingFilterProxy(Shiro)

*

* @param dispatcherServlet

* @return

* @author SHANHY

* @create 2016年1月13日

*/

@Bean

public FilterRegistrationBean filterRegistrationBean() {

FilterRegistrationBean filterRegistration = new FilterRegistrationBean();

filterRegistration.setFilter(new DelegatingFilterProxy("shiroFilter"));

// 该值缺省为false,表示生命周期由SpringApplicationContext管理,设置为true则表示由ServletContainer管理

filterRegistration.addInitParameter("targetFilterLifecycle", "true");

filterRegistration.setEnabled(true);

filterRegistration.addUrlPatterns("/*");

return filterRegistration;

}

@Bean(name = "lifecycleBeanPostProcessor")

public LifecycleBeanPostProcessor getLifecycleBeanPostProcessor() {

return new LifecycleBeanPostProcessor();

}

@Bean

public DefaultAdvisorAutoProxyCreator getDefaultAdvisorAutoProxyCreator() {

DefaultAdvisorAutoProxyCreator daap = new DefaultAdvisorAutoProxyCreator();

daap.setProxyTargetClass(true);

return daap;

}

@Bean(name = "securityManager")

public DefaultWebSecurityManager getDefaultWebSecurityManager(MyShiroCasRealm myShiroCasRealm) {

DefaultWebSecurityManager dwsm = new DefaultWebSecurityManager();

dwsm.setRealm(myShiroCasRealm);

// <!-- 用户授权/认证信息Cache, 采用EhCache 缓存 -->

dwsm.setCacheManager(getEhCacheManager());

// 指定 SubjectFactory

dwsm.setSubjectFactory(new CasSubjectFactory());

return dwsm;

}

@Bean

public AuthorizationAttributeSourceAdvisor getAuthorizationAttributeSourceAdvisor(DefaultWebSecurityManager securityManager) {

AuthorizationAttributeSourceAdvisor aasa = new AuthorizationAttributeSourceAdvisor();

aasa.setSecurityManager(securityManager);

return aasa;

}

/**

* 加载shiroFilter权限控制规则(从数据库读取然后配置)

*

* @author SHANHY

* @create 2016年1月14日

*/

private void loadShiroFilterChain(ShiroFilterFactoryBean shiroFilterFactoryBean, StudentService stuService, IScoreDao scoreDao){

/////////////////////// 下面这些规则配置最好配置到配置文件中 ///////////////////////

Map<String, String> filterChainDefinitionMap = new LinkedHashMap<String, String>();

filterChainDefinitionMap.put(casFilterUrlPattern, "casFilter");// shiro集成cas后,首先添加该规则

// authc:该过滤器下的页面必须验证后才能访问,它是Shiro内置的一个拦截器org.apache.shiro.web.filter.authc.FormAuthenticationFilter

filterChainDefinitionMap.put("/user", "authc");// 这里为了测试,只限制/user,实际开发中请修改为具体拦截的请求规则

// anon:它对应的过滤器里面是空的,什么都没做

logger.info("##################从数据库读取权限规则,加载到shiroFilter中##################");

filterChainDefinitionMap.put("/user/edit/**", "authc,perms[user:edit]");// 这里为了测试,固定写死的值,也可以从数据库或其他配置中读取

filterChainDefinitionMap.put("/login", "anon");

filterChainDefinitionMap.put("/**", "anon");//anon 可以理解为不拦截

shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);

}

/**

* CAS过滤器

*

* @return

* @author SHANHY

* @create 2016117

*/

@Bean(name = "casFilter")

public CasFilter getCasFilter() {

CasFilter casFilter = new CasFilter();

casFilter.setName("casFilter");

casFilter.setEnabled(true);

// 登录失败后跳转的URL,也就是 Shiro 执行 CasRealm 的 doGetAuthenticationInfo 方法向CasServer验证tiket

casFilter.setFailureUrl(loginUrl);// 我们选择认证失败后再打开登录页面

return casFilter;

}

/**

* ShiroFilter<br/>

* 注意这里参数中的 StudentService 和 IScoreDao 只是一个例子,因为我们在这里可以用这样的方式获取到相关访问数据库的对象,

* 然后读取数据库相关配置,配置到 shiroFilterFactoryBean 的访问规则中。实际项目中,请使用自己的Service来处理业务逻辑。

*

* @param myShiroCasRealm

* @param stuService

* @param scoreDao

* @return

* @author SHANHY

* @create 2016年1月14日

*/

@Bean(name = "shiroFilter")

public ShiroFilterFactoryBean getShiroFilterFactoryBean(DefaultWebSecurityManager securityManager, CasFilter casFilter, StudentService stuService, IScoreDao scoreDao) {

ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();

// 必须设置 SecurityManager

shiroFilterFactoryBean.setSecurityManager(securityManager);

// 如果不设置默认会自动寻找Web工程根目录下的"/login.jsp"页面

shiroFilterFactoryBean.setLoginUrl(loginUrl);

// 登录成功后要跳转的连接

shiroFilterFactoryBean.setSuccessUrl("/user");

shiroFilterFactoryBean.setUnauthorizedUrl("/403");

// 添加casFilter到shiroFilter中

Map<String, Filter> filters = new HashMap<>();

filters.put("casFilter", casFilter);

shiroFilterFactoryBean.setFilters(filters);

loadShiroFilterChain(shiroFilterFactoryBean, stuService, scoreDao);

return shiroFilterFactoryBean;

}

}

创建权限认证的 MyShiroCasRealm.java

?

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
package org.springboot.sample.security;

import java.util.List;

import javax.annotation.PostConstruct;

import org.apache.shiro.authz.AuthorizationInfo;

import org.apache.shiro.authz.SimpleAuthorizationInfo;

import org.apache.shiro.cas.CasRealm;

import org.apache.shiro.subject.PrincipalCollection;

import org.slf4j.Logger;

import org.slf4j.LoggerFactory;

import org.springboot.sample.config.ShiroCasConfiguration;

import org.springboot.sample.dao.IUserDao;

import org.springboot.sample.entity.Role;

import org.springboot.sample.entity.User;

import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.stereotype.Service;

import org.springframework.transaction.annotation.Transactional;

public class MyShiroCasRealm extends CasRealm{

private static final Logger logger = LoggerFactory.getLogger(MyShiroCasRealm.class);

@Autowired

private IUserDao userDao;

@PostConstruct

public void initProperty(){

// setDefaultRoles("ROLE_USER");

setCasServerUrlPrefix(ShiroCasConfiguration.casServerUrlPrefix);

// 客户端回调地址

setCasService(ShiroCasConfiguration.shiroServerUrlPrefix + ShiroCasConfiguration.casFilterUrlPattern);

}

/**

* 权限认证,为当前登录的Subject授予角色和权限

* @see 经测试:本例中该方法的调用时机为需授权资源被访问时

* @see 经测试:并且每次访问需授权资源时都会执行该方法中的逻辑,这表明本例中默认并未启用AuthorizationCache

* @see 经测试:如果连续访问同一个URL(比如刷新),该方法不会被重复调用,Shiro有一个时间间隔(也就是cache时间,在ehcache-shiro.xml中配置),超过这个时间间隔再刷新页面,该方法会被执行

*/

@Override

protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {

logger.info("##################执行Shiro权限认证##################");

//获取当前登录输入的用户名,等价于(String) principalCollection.fromRealm(getName()).iterator().next();

String loginName = (String)super.getAvailablePrincipal(principalCollection);

//到数据库查是否有此对象

User user=userDao.findByName(loginName);// 实际项目中,这里可以根据实际情况做缓存,如果不做,Shiro自己也是有时间间隔机制,2分钟内不会重复执行该方法

if(user!=null){

//权限信息对象info,用来存放查出的用户的所有的角色(role)及权限(permission)

SimpleAuthorizationInfo info=new SimpleAuthorizationInfo();

//用户的角色集合

info.setRoles(user.getRolesName());

//用户的角色对应的所有权限,如果只使用角色定义访问权限,下面的四行可以不要

List<Role> roleList=user.getRoleList();

for (Role role : roleList) {

info.addStringPermissions(role.getPermissionsName());

}

// 或者按下面这样添加

//添加一个角色,不是配置意义上的添加,而是证明该用户拥有admin角色

// simpleAuthorInfo.addRole("admin");

//添加权限

// simpleAuthorInfo.addStringPermission("admin:manage");

// logger.info("已为用户[mike]赋予了[admin]角色和[admin:manage]权限");

return info;

}

// 返回null的话,就会导致任何用户访问被拦截的请求时,都会自动跳转到unauthorizedUrl指定的地址

return null;

}

}

在Controller中添加一个方法,用于将登录URL简单化,提供一个重定向功能

@RequestMapping(value="/login",method=RequestMethod.GET)

public String loginForm(Model model){

model.addAttribute("user", new User());

// return "login";

return "redirect:" + ShiroCasConfiguration.loginUrl;

}

本文主要是介绍如何在Spring Boot中集成Shiro+Cas,并非一个从零创建工程到整体完成的介绍。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持快网idc。

原文链接:http://blog.csdn.net/catoop/article/details/50534006

收藏 (0) 打赏

感谢您的支持,我会继续努力的!

打开微信/支付宝扫一扫,即可进行扫码打赏哦,分享从这里开始,精彩与您同在
点赞 (0)

声明:本站所有文章,如无特殊说明或标注,均为本站原创发布。任何个人或组织,在未征得本站同意时,禁止复制、盗用、采集、发布本站内容到任何网站、书籍等各类媒体平台。如若本站内容侵犯了原著者的合法权益,可联系我们进行处理。

快网idc优惠网 建站教程 详解Spring Boot 集成Shiro和CAS https://www.kuaiidc.com/116454.html

相关文章

发表评论
暂无评论