springboot整合shiro

265 阅读6分钟

一、shiro简介
Apache Shiro是一个强大且易用的Java安全框架,执行身份验证、授权、密码学和会话管理。相比较Spring Security,shiro有小巧、简单、易上手等的优点。所以很多框架都在使用shiro。Shiro包含了三个核心组件:Subject, SecurityManager 和 Realms。
1.Subject代表了当前用户的安全操作。
2.SecurityManager则管理所有用户的安全操作。它是Shiro框架的核心,典型的Facade模式,Shiro通过SecurityManager来管理内部组件实例,并通过它来提供安全管理的各种服务。
3.Realm充当了Shiro与应用安全数据间的“桥梁”或者“连接器”。也就是说,当对用户执行认证(登录)和授权(访问控制)验证时,Shiro会从应用配置的Realm中查找用户及其权限信息

二、springboot整合shiro

1.使用maven创建一个jar项目,在pom.xml文件中添加依赖

[XML] _纯文本查看_ _复制代码_

?

01

02

03

04

05

06

07

08

09

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

<`properties`>

<`project.build.sourceEncoding>UTF-8</project.build.sourceEncoding`>

<`java.version>1.8</java.version`>

</`properties`>

<`parent`>

<`groupId>org.springframework.boot</groupId`>

<`artifactId>spring-boot-starter-parent</artifactId`>

<`version>1.3.5.RELEASE</version`>

<`relativePath/><!-- lookup parent from repository -->`

</`parent`>

<`dependencies`>

<`dependency`>

<`groupId>org.springframework.boot</groupId`>

<`artifactId>spring-boot-starter-web</artifactId`>

</`dependency`>

<`dependency`>

<`groupId>org.springframework.boot</groupId`>

<`artifactId>spring-boot-starter-test</artifactId`>

<`scope>test</scope`>

</`dependency`>

<`dependency`>

<`groupId>commons-logging</groupId`>

<`artifactId>commons-logging</artifactId`>

<`version>1.1.3</version`>

</`dependency`>

<`dependency`>

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

<`artifactId>shiro-core</artifactId`>

<`version>1.2.2</version`>

</`dependency`>

<`dependency`>

<`groupId>mysql</groupId`>

<`artifactId>mysql-connector-java</artifactId`>

<`version>5.1.25</version`>

</`dependency`>

<`dependency`>

<`groupId>com.alibaba</groupId`>

<`artifactId>druid</artifactId`>

<`version>0.2.23</version`>

</`dependency`>

<!-- shiro权限控制框架 -->

<`dependency`>

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

<`artifactId>shiro-spring</artifactId`>

<`version>1.3.2</version`>

</`dependency`>

</`dependencies`>

2.编写MyShiroRealm类,实现AuthorizingRealm接口

[Java] _纯文本查看_ _复制代码_

?

01

02

03

04

05

06

07

08

09

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

public`classMyShiroRealmextends`AuthorizingRealm {

/**

* 授权用户权限

*/

@Override

protected`AuthorizationInfo doGetAuthorizationInfo(`

PrincipalCollection principals) {

//获取用户

User user = (User)SecurityUtils.getSubject().getPrincipal();

SimpleAuthorizationInfo info = `new`SimpleAuthorizationInfo();

//获取用户角色

Set<String> roleSet =`new`HashSet<String>();

roleSet.add(`"100002"`);

info.setRoles(roleSet);

//获取用户权限

Set<String> permissionSet =`new`HashSet<String>();

permissionSet.add(`"权限添加"`);

permissionSet.add(`"权限删除"`);

info.setStringPermissions(permissionSet);

return`info;`

}

/**

* 验证用户身份

*/

@Override

protected`AuthenticationInfo doGetAuthenticationInfo(`

AuthenticationToken authcToken)`throws`AuthenticationException {

UsernamePasswordToken token = (UsernamePasswordToken) authcToken;

String username = token.getUsername();

String password = String.valueOf(token.getPassword());

Map<String, Object> map =`new`HashMap<String, Object>();

map.put(`"nickname"`, username);

//密码进行加密处理 明文为 password+name

String paw = password+username;

String pawDES = MyDES.encryptBasedDes(paw);

map.put(`"pswd"`, pawDES);

User user =`new`User();

user.setId(`"112222"`);

user.setUsername(username);

user.setPassword(pawDES);

return`new`SimpleAuthenticationInfo(user, password, getName());

}

}

3.实现ShiroConfiguration

[Java] _纯文本查看_ _复制代码_

?

01

02

03

04

05

06

07

08

09

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

@Configuration

public`class`ShiroConfiguration {

/**

* ShiroFilterFactoryBean 处理拦截资源文件问题。

* 注意:单独一个ShiroFilterFactoryBean配置是或报错的,以为在

* 初始化ShiroFilterFactoryBean的时候需要注入:SecurityManager

*

* Filter Chain定义说明 1、一个URL可以配置多个Filter,使用逗号分隔 2、当设置多个过滤器时,全部验证通过,才视为通过

* 3、部分过滤器可指定参数,如perms,roles

*

*/

@Bean

public`ShiroFilterFactoryBean shiroFilter(SecurityManager securityManager) {`

ShiroFilterFactoryBean shiroFilterFactoryBean =`new`ShiroFilterFactoryBean();

// 必须设置 SecurityManager

shiroFilterFactoryBean.setSecurityManager(securityManager);

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

shiroFilterFactoryBean.setLoginUrl(`"/login"`);

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

shiroFilterFactoryBean.setSuccessUrl(`"/index"`);

// 未授权界面;

shiroFilterFactoryBean.setUnauthorizedUrl(`"/403"`);

//自定义拦截器

Map<String, Filter> filtersMap =`new`LinkedHashMap<String, Filter>();

//限制同一帐号同时在线的个数。

//filtersMap.put("kickout", kickoutSessionControlFilter());

shiroFilterFactoryBean.setFilters(filtersMap);

// 权限控制map.

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

// 配置不会被拦截的链接 顺序判断

// 配置退出过滤器,其中的具体的退出代码Shiro已经替我们实现了

// 从数据库获取动态的权限

// filterChainDefinitionMap.put("/add", "perms[权限添加]");

// <!-- 过滤链定义,从上向下顺序执行,一般将 /**放在最为下边 -->:这是一个坑呢,一不小心代码就不好使了;

// <!-- authc:所有url都必须认证通过才可以访问; anon:所有url都都可以匿名访问-->

//logout这个拦截器是shiro已经实现好了的。

// 从数据库获取

/*List<SysPermissionInit> list = sysPermissionInitService.selectAll();

for (SysPermissionInit sysPermissionInit : list) {

filterChainDefinitionMap.put(sysPermissionInit.getUrl(),

sysPermissionInit.getPermissionInit());

}*/

shiroFilterFactoryBean

.setFilterChainDefinitionMap(filterChainDefinitionMap);

return shiroFilterFactoryBean;

}

@Bean

public SecurityManager securityManager() {

DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();

// 设置realm.

securityManager.setRealm(myShiroRealm());

// 自定义缓存实现 使用redis

//securityManager.setCacheManager(cacheManager());

// 自定义session管理 使用redis

//securityManager.setSessionManager(sessionManager());

//注入记住我管理器;

securityManager.setRememberMeManager(rememberMeManager());

return securityManager;

}

public MyShiroRealm myShiroRealm(){

return new MyShiroRealm();

}

/**

* cookie对象;

* @return

*/

public SimpleCookie rememberMeCookie(){

//这个参数是cookie的名称,对应前端的checkbox的name = rememberMe

SimpleCookie simpleCookie = new SimpleCookie("rememberMe");

//<!-- 记住我cookie生效时间30天 ,单位秒;-->

simpleCookie.setMaxAge(2592000);

return simpleCookie;

}

/**

* cookie管理对象;记住我功能

* @return

*/

public`CookieRememberMeManager rememberMeManager(){`

CookieRememberMeManager cookieRememberMeManager =`new`CookieRememberMeManager();

cookieRememberMeManager.setCookie(rememberMeCookie());

//rememberMe cookie加密的密钥 建议每个项目都不一样 默认AES算法 密钥长度(128 256 512 位)

cookieRememberMeManager.setCipherKey(Base64.decode(`"3AvVhmFLUs0KTA3Kprsdag=="`));

return`cookieRememberMeManager;`

}

}

4.编写LoginController类测试Shiro

[Java] _纯文本查看_ _复制代码_

?

01

02

03

04

05

06

07

08

09

10

11

12

13

14

15

16

17

18

19

20

21

@RestController

public`class`LoginController {

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

public`String login(String username, String password,String vcode,Boolean rememberMe){`

System.out.println(username);

UsernamePasswordToken token =`new`UsernamePasswordToken(username, password,rememberMe);

SecurityUtils.getSubject().login(token);

return`"loginSuccess"`;

}

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

public`String home(){`

Subject subject = SecurityUtils.getSubject();

User principal = (User)subject.getPrincipal();

return`"Home"`;

}

}

引自博客:blog.csdn.net/u012343...