必看
本文为作者自己的学习记录,仅供参考,切勿直接粘贴使用
1. 引入Shiro依赖
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-spring-boot-web-starter</artifactId>
<version>1.13.0</version>
</dependency>
2.Shiro配置文件
- myUserRealm 自定义的realme ,里面就是登录的规则,要从数据库中拿到数据价格shiro
- securityManager 核心方法,自定义的realme要在这个注册才会生效
- shiroFilter 配置白名单 anon 放行; authc 拦截
@Configuration
public class ShiroConfiguration {
@Resource
private ShiroProperties properties;
@Bean
public MyUserRealm myUserRealm(HashedCredentialsMatcher hashedCredentialsMatcher) {
MyUserRealm myUserRealm = new MyUserRealm();
//注册加密的算法
myUserRealm.setCredentialsMatcher(hashedCredentialsMatcher);
return myUserRealm;
}
@Bean
public DefaultWebSecurityManager securityManager(MyUserRealm myUserRealm) {
DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
securityManager.setRealm(myUserRealm);
return securityManager;
}
/**
* 白名单
*/
@Bean
public ShiroFilterChainDefinition shiroFilter() {
DefaultShiroFilterChainDefinition definition = new DefaultShiroFilterChainDefinition();
properties.getList().forEach(path -> definition.addPathDefinition(path, "anon"));
definition.addPathDefinition("/**", "authc");
return definition;
}
/**
* @function 告诉shiro 密码的加密算法 ,还要在自定义realm中注册
* @Time 2024/4/30 17:24
*/
@Bean
public HashedCredentialsMatcher hashedCredentialsMatcher() {
HashedCredentialsMatcher matcher = new HashedCredentialsMatcher();
//加密算法 更加密工具类保持一致
matcher.setHashAlgorithmName(Md5Hash.ALGORITHM_NAME);
//加密次数
matcher.setHashIterations(ShiroUtils.HASH_ITERATIONS);
return matcher;
}
}
3.定义properties类和yml
propertice 中定义了一个List用来接收白名单的路径 yml中就是基本配置
@Data
@Component
@ConfigurationProperties("shiro.white")
public class ShiroProperties {
private List<String> list;
}
# shiro配置
shiro:
white:
list:
- "/member/login"
- "/member/register"
- "/member/un/auth" #失败
- "/druid/*"
# 放行 v3 swagger
- "/swagger**/**"
- "/webjars/**"
- "/doc.html"
- "/v3/**"
loginUrl: "/member/un/auth"
4.自定义Realm
public class MyUserRealm extends AuthenticatingRealm {
@Resource
private UserShiroMapper userShiroMapper;
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
String username = (String) token.getPrincipal();
//判断用户名是否为空
if (Objects.isNull(username)) {
throw new ServiceException(ResponseCode.USER_LOGIN_ERROR);
}
//根据用户名查询用户信息
User user = userShiroMapper.getUser(username);
//用户名不存在
if (Objects.isNull(user)) {
throw new ServiceException(ResponseCode.USER_NAME_ERROR);
}
//用户已被锁定
if (user.getUserStatus() == 1) {
throw new ServiceException(ResponseCode.USER_LOCK_ERROR);
}
//返回给前端的数据
UserVo userVo = BeanConvertUtils.convertTo(user, UserVo::new);
//1.用户所有信息存在session 2.数据库里的用户密码 3.加密盐 4.客户端传来的用户名
return new SimpleAuthenticationInfo(userVo, user.getUserPassword(), null, username);
}
}
5.Shiro入口
@PostMapping("/userLogin")
public String userLogin(@RequestBody UserLoginQo userLoginQo) {
//获取shiro的入口对象 Subject 保持当前用户对象
Subject subject = SecurityUtils.getSubject();
UsernamePasswordToken usernamePasswordToken = new UsernamePasswordToken(userLoginQo.getUsername(), userLoginQo.getPassword());
subject.login(usernamePasswordToken);
subject.getPrincipal()//登录成功可以获取存入session的用户数据
return "OK";
}