0%

springBoot整合shiro

文章字数:455,阅读全文大约需要1分钟

shiro是一个可以管理项目权限的框架

springBoot中引入

maven依赖添加

1
2
3
4
5
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-spring</artifactId>
<version>1.4.0</version>
</dependency>

密码加密工具类

shiro提供了加密、生成随机盐的方法,封装成工具类

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
import org.apache.shiro.crypto.SecureRandomNumberGenerator;
import org.apache.shiro.crypto.RandomNumberGenerator;
import org.apache.shiro.crypto.hash.SimpleHash;
import org.apache.shiro.util.ByteSource;

/**
* 密码加密工具类
*/
public class PasswordHelper{
//随机字符串生成器
private RandomNumberGenerator randomOb = new RandomNumberGenerator();

//散列算法名(md5方式)
private static final String ALGORITHM_NAME = "md5";

//散列迭代次数
private static final int HASH_ITERATION = 2;

/**
* 加密用户
* @param user 用户,用户名(name)、密码(pwd)、盐\加密因子(salt)
*/
public void encryptPassword(User user){
//生成加密因子,保存盐。
user.setSalt(randomOb.nextBytes().toHex());
//加密密码 SimpleHash(算法名,密码,盐的byte,次数).toHex()
String newPassword = new SimpleHash(ALGORITHM_NAME ,user.getPwd,ByteSource.Util.bytes(user.getSalt()),HASH_ITERATION).toHex();
//更新密码
user.setPwd(newPassword );
}
}

自定义Realm

shiro需要我们提供doGetAuthenticationInfodoGetAuthorizationInfo的实现,已完成登录认证和权限信息。
自定义Realm,继承与AuthorizingRealm

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

/*
* 为shiro提供登录验证和权限提取
*/
public class EnceladusShiroRealm extends AuthorizingRealm{
//用户操作业务层
@Autowired
private UserService userService;

/*
* 提供用户角色和权限获取的逻辑
*/
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
//需要返回的权限信息
SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo();
String userName = (String) principals.getPrimaryPrincipal();
User user = userService.findUserByName(userName);
for (SysRole role : user.getRoles()) {
//设置角色
authorizationInfo.addRole(role.getRole());
for (SysPermission permission : role.getPermissions()) {
//设置权限
authorizationInfo.addStringPermission(permission.getName());
}
}
return authorizationInfo;
}

@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
//通过token获取用户名
String userName = (String) token.getPrincipal();
User user = userService.findUserByName(username);
if (user == null) return null;
SimpleAuthenticationInfo authenticationInfo = new SimpleAuthenticationInfo(
user.getUsername(),
user.getPassword(),
ByteSource.Util.bytes(user.getCredentialsSalt()),
getName());
return authenticationInfo;
}
}

shiro配置

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
@Configuration
public class ShiroConfig {
//配置权限
@Bean
public ShiroFilterFactoryBean shirFilter(SecurityManager securityManager) {
ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
shiroFilterFactoryBean.setSecurityManager(securityManager);

Map<String, String> filterChainDefinitionMap = new HashMap<String, String>();
shiroFilterFactoryBean.setLoginUrl("/login");
shiroFilterFactoryBean.setUnauthorizedUrl("/unauthc");
shiroFilterFactoryBean.setSuccessUrl("/home/index");

filterChainDefinitionMap.put("/*", "anon");
filterChainDefinitionMap.put("/authc/index", "authc");
filterChainDefinitionMap.put("/authc/admin", "roles[admin]");
filterChainDefinitionMap.put("/authc/renewable", "perms[Create,Update]");
filterChainDefinitionMap.put("/authc/removable", "perms[Delete]");
shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);
return shiroFilterFactoryBean;
}

/*
* 提供散列算法的信息
*/
@Bean
public HashedCredentialsMatcher hashedCredentialsMatcher() {
HashedCredentialsMatcher hashedCredentialsMatcher = new HashedCredentialsMatcher();
hashedCredentialsMatcher.setHashAlgorithmName(PasswordHelper.ALGORITHM_NAME); // 散列算法
hashedCredentialsMatcher.setHashIterations(PasswordHelper.HASH_ITERATIONS); // 散列次数
return hashedCredentialsMatcher;
}

/*
* 设置加密算法
*/
@Bean
public EnceladusShiroRealm shiroRealm() {
//自己实现的Realm
EnceladusShiroRealm shiroRealm = new EnceladusShiroRealm();
shiroRealm.setCredentialsMatcher(hashedCredentialsMatcher()); // 设置加密算法
return shiroRealm;
}

/*
* 设置安全管理类的realm为上面写的realm
*/
@Bean
public SecurityManager securityManager() {
DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
securityManager.setRealm(shiroRealm());
return securityManager;
}

@Bean
public PasswordHelper passwordHelper() {
return new PasswordHelper();
}
}
1
2
3
4
5
常用的过滤器如下:
authc:所有已登陆用户可访问
roles:有指定角色的用户可访问,通过[ ]指定具体角色,这里的角色名称与数据库中配置一致
perms:有指定权限的用户可访问,通过[ ]指定具体权限,这里的权限名称与数据库中配置一致
anon:所有用户可访问,通常作为指定页面的静态资源时使用

test

获取权限的操作

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
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.IncorrectCredentialsException;
import org.apache.shiro.authc.UnknownAccountException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.subject.Subject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import com.learnhow.springboot.web.PasswordHelper;
import com.learnhow.springboot.web.entity.User;
import com.learnhow.springboot.web.service.UserService;

@RestController
@RequestMapping
public class HomeController {
@Autowired
private UserService userService;
@Autowired
private PasswordHelper passwordHelper;

@GetMapping("login")
public Object login() {
return "Here is Login page";
}

@GetMapping("unauthc")
public Object unauthc() {
return "Here is Unauthc page";
}

@GetMapping("doLogin")
public Object doLogin(@RequestParam String username, @RequestParam String password) {
UsernamePasswordToken token = new UsernamePasswordToken(username, password);
Subject subject = SecurityUtils.getSubject();
try {
subject.login(token);
} catch (IncorrectCredentialsException ice) {
return "password error!";
} catch (UnknownAccountException uae) {
return "username error!";
}

User user = userService.findUserByName(username);
subject.getSession().setAttribute("user", user);
return "SUCCESS";
}

@GetMapping("register")
public Object register(@RequestParam String username, @RequestParam String password) {
User user = new User();
user.setUsername(username);
user.setPassword(password);
passwordHelper.encryptPassword(user);

userService.saveUser(user);
return "SUCCESS";
}
}

权限拦截

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
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.subject.Subject;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import com.learnhow.springboot.web.entity.User;

@RestController
@RequestMapping("authc")
public class AuthcController {

@GetMapping("index")
public Object index() {
Subject subject = SecurityUtils.getSubject();
User user = (User) subject.getSession().getAttribute("user");
return user.toString();
}

@GetMapping("admin")
public Object admin() {
return "Welcome Admin";
}

// delete
@GetMapping("removable")
public Object removable() {
return "removable";
}

// insert & update
@GetMapping("renewable")
public Object renewable() {
return "renewable";
}
}