spring boot 1.5.4 集成shiro+cas,实现单点登录和权限控制

2025-05-29 0 107

1.添加maven依赖(先安装好cas-server-3.5.2,安装步骤请查看本文参考文章)

?

1
2

3

4

5

6

7

8

9

10

11

12

13

14

15
<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>

2.启动累添加@ServletComponentScan注解

?

1
2

3

4

5

6

7

8

9

10

11

12

13
@SpringBootApplication

public class Application {

/**

* main function

* @param args params

*/

public static void main(String[] args){

ConfigurableApplicationContext context = SpringApplication.run(Application.class,args);

//test if a xml bean inject into springcontext successful

User user = (User)context.getBean("user1");

System.out.println(JSONObject.toJSONString(user));

}

}

3.配置shiro+cas

?

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

187

188

189

190

191

192

193

194

195

196

197

198

199

200

201

202

203

204

205

206

207

208

209

210

211

212

213

214

215

216

217
package com.hdwang.config.shiroCas;

import com.hdwang.dao.UserDao;

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.filter.authc.LogoutFilter;

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

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

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

import org.slf4j.Logger;

import org.slf4j.LoggerFactory;

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

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

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 org.springframework.core.Ordered;

import org.springframework.web.filter.DelegatingFilterProxy;

import javax.servlet.Filter;

import javax.servlet.annotation.WebListener;

import java.util.HashMap;

import java.util.LinkedHashMap;

import java.util.Map;

/**

* Created by hdwang on 2017/6/20.

* shiro+cas 配置

*/

@Configuration

public class ShiroCasConfiguration {

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

// cas server地址

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:8081";

// casFilter UrlPattern

public static final String casFilterUrlPattern = "/cas";

// 登录地址

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

// 登出地址

public static final String logoutUrl = casLogoutUrl+"?service="+shiroServerUrlPrefix;

// 登录成功地址

public static final String loginSuccessUrl = "/home";

// 权限认证失败跳转地址

public static final String unauthorizedUrl = "/error/403.html";

@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);

//realm.setCasServerUrlPrefix(ShiroCasConfiguration.casServerUrlPrefix);

// 客户端回调地址

//realm.setCasService(ShiroCasConfiguration.shiroServerUrlPrefix + ShiroCasConfiguration.casFilterUrlPattern);

return realm;

}

/**

* 注册单点登出listener

* @return

*/

@Bean

public ServletListenerRegistrationBean singleSignOutHttpSessionListener(){

ServletListenerRegistrationBean bean = new ServletListenerRegistrationBean();

bean.setListener(new SingleSignOutHttpSessionListener());

// bean.setName(""); //默认为bean name

bean.setEnabled(true);

//bean.setOrder(Ordered.HIGHEST_PRECEDENCE); //设置优先级

return bean;

}

/**

* 注册单点登出filter

* @return

*/

@Bean

public FilterRegistrationBean singleSignOutFilter(){

FilterRegistrationBean bean = new FilterRegistrationBean();

bean.setName("singleSignOutFilter");

bean.setFilter(new SingleSignOutFilter());

bean.addUrlPatterns("/*");

bean.setEnabled(true);

//bean.setOrder(Ordered.HIGHEST_PRECEDENCE);

return bean;

}

/**

* 注册DelegatingFilterProxy(Shiro)

*

* @return

* @author SHANHY

* @create 2016年1月13日

*/

@Bean

public FilterRegistrationBean delegatingFilterProxy() {

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;

}

/**

* CAS过滤器

*

* @return

* @author SHANHY

* @create 2016年1月17日

*/

@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 securityManager

* @param casFilter

* @param userDao

* @return

* @author SHANHY

* @create 2016年1月14日

*/

@Bean(name = "shiroFilter")

public ShiroFilterFactoryBean getShiroFilterFactoryBean(DefaultWebSecurityManager securityManager, CasFilter casFilter, UserDao userDao) {

ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();

// 必须设置 SecurityManager

shiroFilterFactoryBean.setSecurityManager(securityManager);

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

shiroFilterFactoryBean.setLoginUrl(loginUrl);

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

shiroFilterFactoryBean.setSuccessUrl(loginSuccessUrl);

shiroFilterFactoryBean.setUnauthorizedUrl(unauthorizedUrl);

// 添加casFilter到shiroFilter中

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

filters.put("casFilter", casFilter);

// filters.put("logout",logoutFilter());

shiroFilterFactoryBean.setFilters(filters);

loadShiroFilterChain(shiroFilterFactoryBean, userDao);

return shiroFilterFactoryBean;

}

/**

* 加载shiroFilter权限控制规则(从数据库读取然后配置),角色/权限信息由MyShiroCasRealm对象提供doGetAuthorizationInfo实现获取来的

*

* @author SHANHY

* @create 2016年1月14日

*/

private void loadShiroFilterChain(ShiroFilterFactoryBean shiroFilterFactoryBean, UserDao userDao){

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

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

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

// anon: 可以理解为不拦截

// user: 登录了就不拦截

// roles["admin"] 用户拥有admin角色

// perms["permission1"] 用户拥有permission1权限

// filter顺序按照定义顺序匹配,匹配到就验证,验证完毕结束。

// url匹配通配符支持:? * **,分别表示匹配1个,匹配0-n个(不含子路径),匹配下级所有路径

//1.shiro集成cas后,首先添加该规则

filterChainDefinitionMap.put(casFilterUrlPattern, "casFilter");

//filterChainDefinitionMap.put("/logout","logout"); //logut请求采用logout filter

//2.不拦截的请求

filterChainDefinitionMap.put("/css/**","anon");

filterChainDefinitionMap.put("/js/**","anon");

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

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

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

//3.拦截的请求(从本地数据库获取或者从casserver获取(webservice,http等远程方式),看你的角色权限配置在哪里)

filterChainDefinitionMap.put("/user", "authc"); //需要登录

filterChainDefinitionMap.put("/user/add/**", "authc,roles[admin]"); //需要登录,且用户角色为admin

filterChainDefinitionMap.put("/user/delete/**", "authc,perms[\\"user:delete\\"]"); //需要登录,且用户有权限为user:delete

//4.登录过的不拦截

filterChainDefinitionMap.put("/**", "user");

shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);

}

}

?

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
package com.hdwang.config.shiroCas;

import javax.annotation.PostConstruct;

import com.hdwang.dao.UserDao;

import com.hdwang.entity.User;

import org.apache.shiro.SecurityUtils;

import org.apache.shiro.authc.AuthenticationInfo;

import org.apache.shiro.authc.AuthenticationToken;

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.springframework.beans.factory.annotation.Autowired;

import java.util.HashSet;

import java.util.Set;

/**

* Created by hdwang on 2017/6/20.

* 安全数据源

*/

public class MyShiroCasRealm extends CasRealm{

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

@Autowired

private UserDao userDao;

@PostConstruct

public void initProperty(){

// setDefaultRoles("ROLE_USER");

setCasServerUrlPrefix(ShiroCasConfiguration.casServerUrlPrefix);

// 客户端回调地址

setCasService(ShiroCasConfiguration.shiroServerUrlPrefix + ShiroCasConfiguration.casFilterUrlPattern);

}

// /**

// * 1、CAS认证 ,验证用户身份

// * 2、将用户基本信息设置到会话中(不用了,随时可以获取的)

// */

// @Override

// protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) {

//

// AuthenticationInfo authc = super.doGetAuthenticationInfo(token);

//

// String account = (String) authc.getPrincipals().getPrimaryPrincipal();

//

// User user = userDao.getByName(account);

// //将用户信息存入session中

// SecurityUtils.getSubject().getSession().setAttribute("user", user);

//

// return authc;

// }

/**

* 权限认证,为当前登录的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);

//到数据库查是否有此对象(1.本地查询 2.可以远程查询casserver 3.可以由casserver带过来角色/权限其它信息)

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

if(user!=null){

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

SimpleAuthorizationInfo info=new SimpleAuthorizationInfo();

//给用户添加角色(让shiro去验证)

Set<String> roleNames = new HashSet<>();

if(user.getName().equals("boy5")){

roleNames.add("admin");

}

info.setRoles(roleNames);

if(user.getName().equals("李四")){

//给用户添加权限(让shiro去验证)

info.addStringPermission("user:delete");

}

// 或者按下面这样添加

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

// simpleAuthorInfo.addRole("admin");

//添加权限

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

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

return info;

}

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

return null;

}

}

?

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
package com.hdwang.controller;

import com.hdwang.config.shiroCas.ShiroCasConfiguration;

import com.hdwang.entity.User;

import org.springframework.stereotype.Controller;

import org.springframework.ui.Model;

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

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

import javax.servlet.http.HttpSession;

/**

* Created by hdwang on 2017/6/21.

* 跳转至cas server去登录(一个入口)

*/

@Controller

@RequestMapping("")

public class CasLoginController {

/**

* 一般用不到

* @param model

* @return

*/

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

public String loginForm(Model model){

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

// return "login";

return "redirect:" + ShiroCasConfiguration.loginUrl;

}

@RequestMapping(value = "logout", method = { RequestMethod.GET,

RequestMethod.POST })

public String loginout(HttpSession session)

{

return "redirect:"+ShiroCasConfiguration.logoutUrl;

}

}

?

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
package com.hdwang.controller;

import com.alibaba.fastjson.JSONObject;

import com.hdwang.entity.User;

import com.hdwang.service.datajpa.UserService;

import org.apache.shiro.SecurityUtils;

import org.apache.shiro.mgt.SecurityManager;

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

import org.springframework.stereotype.Controller;

import org.springframework.ui.ModelMap;

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

import javax.servlet.http.HttpServletRequest;

import javax.servlet.http.HttpSession;

/**

* Created by hdwang on 2017/6/19.

*/

@Controller

@RequestMapping("/home")

public class HomeController {

@Autowired

UserService userService;

@RequestMapping("")

public String index(HttpSession session, ModelMap map, HttpServletRequest request){

// User user = (User) session.getAttribute("user");

System.out.println(request.getUserPrincipal().getName());

System.out.println(SecurityUtils.getSubject().getPrincipal());

User loginUser = userService.getLoginUser();

System.out.println(JSONObject.toJSONString(loginUser));

map.put("user",loginUser);

return "home";

}

}

4.运行验证

登录

访问:http://localhost:8081/home

跳转至:https://localhost:8443/cas/login?service=http://localhost:8081/cas

输入正确用户名密码登录跳转回:http://localhost:8081/cas?ticket=ST-203-GUheN64mOZec9IWZSH1B-cas01.example.org

最终跳回:http://localhost:8081/home

登出

访问:http://localhost:8081/logout

跳转至:https://localhost:8443/cas/logout?service=http://localhost:8081

由于未登录,又执行登录步骤,所以最终返回https://localhost:8443/cas/login?service=http://localhost:8081/cas

这次登录成功后返回:http://localhost:8081/

cas server端登出(也行)

访问:https://localhost:8443/cas/logout

再访问:http://localhost:8081/home 会跳转至登录页,perfect!

以上所述是小编给大家介绍的spring boot 1.5.4 集成shiro+cas,实现单点登录权限控制,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对快网idc网站的支持!

原文链接:http://www.cnblogs.com/hdwang/archive/2017/06/22/7064492.html

收藏 (0) 打赏

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

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

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

快网idc优惠网 建站教程 spring boot 1.5.4 集成shiro+cas,实现单点登录和权限控制 https://www.kuaiidc.com/115809.html

相关文章

发表评论
暂无评论