CAS 5.3.1系列之自定义Shiro认证策略(四)

网友投稿 672 2022-05-30

CAS 5.3.1系列之自定义Shiro认证策略(四)

CAS官方文档是介绍基于配置实现shiro认证的,可以参考官方文档,不过我们也可以通过自定义认证策略的方式实现jdbc认证,pom先加入相关jar

org.apereo.cas cas-server-core-authentication-api ${cas.version} org.apereo.cas cas-server-core-configuration-api ${cas.version} org.apereo.cas cas-server-support-generic ${cas.version}

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

如果要用公网提供的基于配置实现的,需要加入:

org.apereo.cas cas-server-support-shiro-authentication ${cas.version}

1

2

3

4

5

6

要自定义shiroRealm的,加入shiro相关jar:

org.apache.shiro shiro-spring 1.4.0

1

2

3

4

5

实现一个Shiro Realm类,仅供参考:

import org.apache.shiro.SecurityUtils; import org.apache.shiro.authc.*; import org.apache.shiro.authz.AuthorizationInfo; import org.apache.shiro.authz.SimpleAuthorizationInfo; import org.apache.shiro.realm.AuthorizingRealm; import org.apache.shiro.session.Session; import org.apache.shiro.subject.PrincipalCollection; import org.apache.shiro.subject.Subject; import org.muses.jeeplatform.cas.user.model.User; import org.muses.jeeplatform.cas.user.service.UserService; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.jdbc.core.BeanPropertyRowMapper; import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.jdbc.datasource.DriverManagerDataSource; /** *

 * * 
* *
 * @author mazq * 修改记录 * 修改后版本: 修改人: 修改日期: 2020/04/26 11:33 修改内容: * 
*/ public class ShiroAuthorizingRealm extends AuthorizingRealm { Logger LOG = LoggerFactory.getLogger(ShiroAuthorizingRealm.class); /**注解引入业务类**/ //@Autowired //UserService userService; /** * 登录信息和用户验证信息验证(non-Javadoc) * @see org.apache.shiro.realm.AuthenticatingRealm#doGetAuthenticationInfo(AuthenticationToken) */ @Override protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException { String username = (String)token.getPrincipal(); //得到用户名 String password = new String((char[])token.getCredentials()); //得到密码 LOG.info("Shiro doGetAuthenticationInfo>> username:{},password:{}",username,password); //User user = userService.findByUsername(username); // JDBC模板依赖于连接池来获得数据的连接,所以必须先要构造连接池 DriverManagerDataSource dataSource = new DriverManagerDataSource(); dataSource.setDriverClassName("com.mysql.jdbc.Driver"); dataSource.setUrl("jdbc:mysql://192.168.0.152:33306/jeeplatform"); dataSource.setUsername("root"); dataSource.setPassword("minstone"); // 创建JDBC模板 JdbcTemplate jdbcTemplate = new JdbcTemplate(); jdbcTemplate.setDataSource(dataSource); String sql = "SELECT * FROM sys_user WHERE username = ?"; User user = (User) jdbcTemplate.queryForObject(sql, new Object[]{username}, new BeanPropertyRowMapper(User.class)); Subject subject = getCurrentExecutingSubject(); //获取Shiro管理的Session Session session = getShiroSession(subject); //Shiro添加会话 session.setAttribute("username", username); session.setAttribute(ShiroConsts.SESSION_USER, user); /**检测是否有此用户 **/ if(user == null){ throw new UnknownAccountException();//没有找到账号异常 } /**检验账号是否被锁定 **/ if(Boolean.TRUE.equals(user.getLocked())){ throw new LockedAccountException();//抛出账号锁定异常 } /**AuthenticatingRealm使用CredentialsMatcher进行密码匹配**/ if(null != username && null != password){ return new SimpleAuthenticationInfo(username, password, getName()); }else{ return null; } } /** * 授权查询回调函数, 进行鉴权但缓存中无用户的授权信息时调用,负责在应用程序中决定用户的访问控制的方法(non-Javadoc) * @see AuthorizingRealm#doGetAuthorizationInfo(PrincipalCollection) */ @Override protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection pc) { String username = (String)pc.getPrimaryPrincipal(); SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo(); // authorizationInfo.setRoles(userService.getRoles(username)); // authorizationInfo.setStringPermissions(userService.getPermissions(username)); System.out.println("Shiro授权"); return authorizationInfo; } @Override public void clearCachedAuthorizationInfo(PrincipalCollection principals) { super.clearCachedAuthorizationInfo(principals); } @Override public void clearCachedAuthenticationInfo(PrincipalCollection principals) { super.clearCachedAuthenticationInfo(principals); } @Override public void clearCache(PrincipalCollection principals) { super.clearCache(principals); } protected Subject getCurrentExecutingSubject(){ return SecurityUtils.getSubject(); } protected Session getShiroSession(Subject subject){ return subject.getSession(); } }

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

自定义授权handler类实现AbstractUsernamePasswordAuthenticationHandler抽象类:

package org.muses.jeeplatform.cas.authentication.handler; import org.apache.shiro.SecurityUtils; import org.apache.shiro.authc.*; import org.apache.shiro.session.Session; import org.apache.shiro.subject.Subject; import org.apereo.cas.authentication.*; import org.apereo.cas.authentication.AuthenticationException; import org.apereo.cas.authentication.exceptions.AccountDisabledException; import org.apereo.cas.authentication.handler.support.AbstractPreAndPostProcessingAuthenticationHandler; import org.apereo.cas.authentication.handler.support.AbstractUsernamePasswordAuthenticationHandler; import org.apereo.cas.authentication.principal.PrincipalFactory; import org.apereo.cas.services.ServicesManager; import javax.security.auth.login.AccountLockedException; import javax.security.auth.login.AccountNotFoundException; import javax.security.auth.login.CredentialExpiredException; import javax.security.auth.login.FailedLoginException; import java.security.GeneralSecurityException; /** *

 * * 
* *
 * @author mazq * 修改记录 * 修改后版本: 修改人: 修改日期: 2020/04/26 11:03 修改内容: * 
*/ public class ShiroAuthenticationHandler extends AbstractUsernamePasswordAuthenticationHandler { public ShiroAuthenticationHandler(String name, ServicesManager servicesManager, PrincipalFactory principalFactory, Integer order) { super(name, servicesManager, principalFactory, order); } @Override protected AuthenticationHandlerExecutionResult authenticateUsernamePasswordInternal(UsernamePasswordCredential credential, String originalPassword) throws GeneralSecurityException, PreventedException { try { UsernamePasswordToken token = new UsernamePasswordToken(credential.getUsername(), credential.getPassword()); if (credential instanceof RememberMeUsernamePasswordCredential) { token.setRememberMe(RememberMeUsernamePasswordCredential.class.cast(credential).isRememberMe()); } Subject subject = getCurrentExecutingSubject(); subject.login(token); //获取Shiro管理的Session //Session session = getShiroSession(subject); final String username = subject.getPrincipal().toString(); return createHandlerResult(credential, this.principalFactory.createPrincipal(username)); } catch (final UnknownAccountException uae) { throw new AccountNotFoundException(uae.getMessage()); } catch (final IncorrectCredentialsException ice) { throw new FailedLoginException(ice.getMessage()); } catch (final LockedAccountException | ExcessiveAttemptsException lae) { throw new AccountLockedException(lae.getMessage()); } catch (final ExpiredCredentialsException eae) { throw new CredentialExpiredException(eae.getMessage()); } catch (final DisabledAccountException eae) { throw new AccountDisabledException(eae.getMessage()); } catch (final AuthenticationException e) { throw new FailedLoginException(e.getMessage()); } } protected Subject getCurrentExecutingSubject(){ return SecurityUtils.getSubject(); } protected Session getShiroSession(Subject subject){ return subject.getSession(); } @Override public boolean supports(Credential credential) { return false; } }

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

同理实现一个Shiro配置类:

package org.muses.jeeplatform.cas.authentication.config; import org.apache.shiro.mgt.SecurityManager; import org.apache.shiro.spring.web.ShiroFilterFactoryBean; import org.apache.shiro.web.mgt.DefaultWebSecurityManager; import org.apereo.cas.authentication.AuthenticationEventExecutionPlan; import org.apereo.cas.authentication.AuthenticationEventExecutionPlanConfigurer; import org.apereo.cas.authentication.AuthenticationHandler; import org.apereo.cas.authentication.PrePostAuthenticationHandler; import org.apereo.cas.authentication.principal.DefaultPrincipalFactory; import org.apereo.cas.configuration.CasConfigurationProperties; import org.apereo.cas.services.ServicesManager; import org.muses.jeeplatform.cas.authentication.handler.ShiroAuthenticationHandler; import org.muses.jeeplatform.cas.authentication.handler.UsernamePasswordAuthenticationHandler; import org.muses.jeeplatform.cas.authentication.shiro.ShiroAuthorizingRealm; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.beans.factory.config.MethodInvokingFactoryBean; import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import java.util.LinkedHashMap; import java.util.Map; /** *

 * * 
* *
 * @author mazq * 修改记录 * 修改后版本: 修改人: 修改日期: 2020/04/26 16:35 修改内容: * 
*/ @Configuration("ShiroAuthenticationConfiguration") @EnableConfigurationProperties(CasConfigurationProperties.class) public class ShiroAuthenticationConfiguration implements AuthenticationEventExecutionPlanConfigurer { @Autowired private CasConfigurationProperties casProperties; @Autowired @Qualifier("servicesManager") private ServicesManager servicesManager; //@Bean public ShiroFilterFactoryBean shirFilter(SecurityManager securityManager) { ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean(); shiroFilterFactoryBean.setSecurityManager(securityManager); //-. Map filterChainDefinitionMap = new LinkedHashMap<>(); // 配置不会被拦截的链接 顺序判断 filterChainDefinitionMap.put("/static/**", "anon"); filterChainDefinitionMap.put("/upload/**", "anon"); filterChainDefinitionMap.put("/plugins/**", "anon"); filterChainDefinitionMap.put("/code", "anon"); filterChainDefinitionMap.put("/login", "anon"); filterChainDefinitionMap.put("/logincheck", "anon"); filterChainDefinitionMap.put("/**", "authc"); shiroFilterFactoryBean.setLoginUrl("/login"); shiroFilterFactoryBean.setSuccessUrl("/index"); shiroFilterFactoryBean.setUnauthorizedUrl("/login"); shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap); return shiroFilterFactoryBean; } @Bean public ShiroAuthorizingRealm shiroAuthorizingRealm(){ ShiroAuthorizingRealm myShiroRealm = new ShiroAuthorizingRealm(); //myShiroRealm.setCachingEnabled(false); //启用身份验证缓存,即缓存AuthenticationInfo信息,默认false myShiroRealm.setAuthenticationCachingEnabled(false); //启用授权缓存,即缓存AuthorizationInfo信息,默认false myShiroRealm.setAuthorizationCachingEnabled(false); return myShiroRealm; } @Bean public SecurityManager securityManager(){ DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager(); securityManager.setRealm(shiroAuthorizingRealm()); return securityManager; } /** * Spring静态注入 * @return */ @Bean public MethodInvokingFactoryBean getMethodInvokingFactoryBean(){ MethodInvokingFactoryBean factoryBean = new MethodInvokingFactoryBean(); factoryBean.setStaticMethod("org.apache.shiro.SecurityUtils.setSecurityManager"); factoryBean.setArguments(new Object[]{securityManager()}); return factoryBean; } @Bean public AuthenticationHandler myAuthenticationHandler() { return new ShiroAuthenticationHandler(ShiroAuthenticationHandler.class.getName(), servicesManager, new DefaultPrincipalFactory(), 1); } @Override public void configureAuthenticationExecutionPlan(AuthenticationEventExecutionPlan plan) { plan.registerAuthenticationHandler(myAuthenticationHandler()); } }

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

CAS 5.3.1系列之自定义Shiro认证策略(四)

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

在META-INF文件夹,新增一个命名为spring.factories的文件

org.springframework.boot.autoconfigure.EnableAutoConfiguration=\ org.muses.jeeplatform.cas.authentication.config.ShiroAuthenticationConfiguration

1

2

3

为什么要这样做?因为这样做才能将配置类加载到spring容器,详情需要跟下源码,可以参考我博客:SpringBoot源码学习系列之自动配置原理简介

代码例子参考:github下载链接

详情可以参考官方文档:https://apereo.github.io/cas/5.3.x/installation/Configuration-Properties.html

优质参考博客:

https://www.cnblogs.com/jpeanut/tag/CAS/

https://blog.csdn.net/anumbrella/category_7765386.html

Spring

版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:疯狂JAVA之学习笔记(6)------------标识符和关键字
下一篇:不知道IDEA的这些个性化配置,你怎么能说自己会用它
相关文章