spring boot 整合shiro 最简单配置(默认相关配置,其他自定义配置后面介绍:session使用redis存储,密码加密适配等)
-
相关版本:
-
jdk:17
-
相关依赖包:shiro-spring-boot-web-starter
-
2. 创建spring boot项目
创建spring boot项目就可以,然后复制pom相关的依赖包到pom.xml
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.83</version>
</dependency>
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-spring-boot-web-starter</artifactId>
<version>2.0.0</version>
</dependency>
3. 创建ShiroConfig.java 配置文件
import org.apache.shiro.authc.credential.CredentialsMatcher;
import org.apache.shiro.authc.credential.HashedCredentialsMatcher;
import org.apache.shiro.authc.credential.SimpleCredentialsMatcher;
import org.apache.shiro.realm.Realm;
import org.apache.shiro.session.mgt.SessionManager;
import org.apache.shiro.session.mgt.eis.SessionDAO;
import org.apache.shiro.spring.web.config.DefaultShiroFilterChainDefinition;
import org.apache.shiro.spring.web.config.ShiroFilterChainDefinition;
import org.apache.shiro.web.mgt.CookieRememberMeManager;
import org.apache.shiro.web.servlet.Cookie;
import org.apache.shiro.web.servlet.SimpleCookie;
import org.apache.shiro.web.session.mgt.DefaultWebSessionManager;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import java.security.NoSuchAlgorithmException;
@Configuration
public class ShiroConfig {
@Bean
public ShiroFilterChainDefinition shiroFilterChainDefinition() {
//配置过滤器链,可配置请求过滤
DefaultShiroFilterChainDefinition chainDefinition = new DefaultShiroFilterChainDefinition();
// need to accept POSTs from the login form
//chainDefinition.addPathDefinition("/login/**", "authc");
chainDefinition.addPathDefinition("/login/**", "anon");
chainDefinition.addPathDefinition("/user", "anon");
chainDefinition.addPathDefinition("/favicon.ico", "anon");
chainDefinition.addPathDefinition("/logout", "logout");
chainDefinition.addPathDefinition("/userCreate","authc");
return chainDefinition;
}
//2.0版本 配置realms相关,用户的认证和权限
@Bean("realm")
public Realm getRealms() {
LoginRealm realm = new LoginRealm();
//使用最简单配置器,正常来说密码需要加密加盐等操作,后面介绍
SimpleCredentialsMatcher simple = new SimpleCredentialsMatcher();
realm.setCredentialsMatcher(simple);
//自定义匹配器
//realm.setCredentialsMatcher(getCredentialsMatcher());
return realm;
}
//session管理,使用默认配置即可,自定义session后面介绍
@Bean("sessionManager")
public SessionManager getSessionManager(SessionDAO sessionDAO, CacheManagerRedis cacheManagerRedis) {
DefaultWebSessionManager sessionManager = new DefaultWebSessionManager();
//session信息 存redis 自定义sessionDao
//sessionManager.setSessionDAO(sessionDAO);
//缓存信息也存进redis,使用插件包org.crazycake(sessionDAO也可使用)
//sessionManager.setCacheManager(cacheManagerRedis);
return sessionManager;
}
}
4. 创建UserReaml.java,用于身份认证和权限认证
package com.springboot.test.realms;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.lang.util.ByteSource;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.springframework.stereotype.Service;
import java.util.List;
public class LoginRealm extends AuthorizingRealm {
/**
* 权限认证/可从DB获取数据
* @param principalCollection
* @return
*/
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
//db 获取角色
List role = UserUtils.getRole();
info.addRoles(role);
//获取资源权限
List resources = UserUtils.getResources();
info.addStringPermissions(resources);
return info;
}
/**
* 认证实现/登录校验
* @param token
* @return
* @throws AuthenticationException
*/
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
SimpleAuthenticationInfo info = new SimpleAuthenticationInfo();
String name = (String) token.getPrincipal();
User user = UserUtils.getUser(name);
if (user == null) {//用户不存在
throw new AuthenticationException();
}
/*Subject user = SecurityUtils.getSubject();
AuthenticationToken tt = new UsernamePasswordToken("user","pwd");
user.login(tt);*/
//1.可以是id或者用户名,唯一标识 2.密码 3.加密salt 4.唯一值
//return new SimpleAuthenticationInfo(name,user.getPwd(), ByteSource.Util.bytes(UserUtils.SALT),getName());
return new SimpleAuthenticationInfo(name, user.getPwd(), getName());
}
}
5.创建用户信息, 方便测试先用集合写死,正常来说应该走数据库查询
package com.springboot.test.realms;
import org.apache.shiro.crypto.hash.Sha256Hash;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class UserUtils {
public final static String SALT = "sprintboot-shiro";
static Map<String, User> map = new HashMap<String, User>();
static {
User user = new User();
user.setId("1");
user.setUsername("wangwu");
String pwd = "888888";
//pwd = new Sha256Hash(pwd, SALT, 1024).toHex();
//System.out.println(pwd);
user.setPwd(pwd);
map.put(user.getUsername(), user);
}
public static User getUser(String username) {
if (map.containsKey(username)) {
return map.get(username);
}
return null;
}
public static List<String> getRole() {
List role = new ArrayList();
role.add("admin");
role.add("root");
return role;
}
public static List<String> getResources() {
List resources = new ArrayList();
resources.add("user:create");
resources.add("user:del");
resources.add("user:upd");
resources.add("user:insert");
return resources;
}
}
6.创建测试TestController.java
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.apache.shiro.subject.Subject;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;
@Controller
public class TestController {
@GetMapping("/login/{username}/{password}")
@ResponseBody
public String login(@PathVariable String username, @PathVariable String password) {
String result = null;
UsernamePasswordToken token = new UsernamePasswordToken();
token.setPassword(password.toCharArray());
token.setUsername(username);
Subject subject = SecurityUtils.getSubject();
try{
subject.login(token);
System.out.println(subject.getSession().getId());
result = subject.getSession().getId().toString();
} catch (Exception e) {
e.printStackTrace();
result = "fail";
}
return result;
}
@RequiresPermissions("user:create")
@GetMapping("/userCreate")
@ResponseBody
public String authorizationUser() {
System.out.println("--------");
return "have userCreate";
}
@GetMapping("/user")
@ResponseBody
public String user() {
Subject sub = SecurityUtils.getSubject();
return sub.getSession().getId().toString();
}
}
7.浏览器访问,测试是否生成相同的sessionId
访问:http://localhost:8080/user 浏览器展示返回sessionid,刷新多次id不变
访问:http://localhost:8080/userCreate 浏览器返回404(没有创建login.jsp),地址变成了http://localhost:8080/login.jsp,因为没有登录
访问:http://localhost:8080/login/wangwu/888888 返回sessionid,则证明登录成功
之后在访问:http://localhost:8080/userCreate 则打印:have userCreate 证明登录成功,并且有user:create权限