API文档:Apache Shiro 1.9.0 API
核心三个对象
- Subject 用户
- SecurityManager 管理所有用户
- Realm 连接数据
第一步:引入依赖
<!--shiro权限认证框架--><dependency><groupId>org.apache.shiro</groupId><artifactId>shiro-spring-boot-web-starter</artifactId><version>1.9.0</version></dependency>
第二步、shiro配置(java)
1.创建UserRealm
```java package com.tj.reggie.config;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.tj.reggie.entity.Users; import com.tj.reggie.service.UsersService; 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.subject.PrincipalCollection; import org.apache.shiro.subject.Subject; import org.springframework.beans.factory.annotation.Autowired;
//自定义的UserRealm public class UserRealm extends AuthorizingRealm { @Autowired //自动加载业务层接口 private UsersService usersService;
//授权@Overrideprotected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {System.out.println("执行了授权AuthorizationInfo");//获取当前登录的用户对象Subject subject = SecurityUtils.getSubject();Long id = (Long) subject.getPrincipal(); //获取用户的id
// //根据用户的id查询当前用户的角色
// Set
// return info; //返回授权信息 return null; }
//认证@Overrideprotected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {System.out.println("执行了认证AuthenticationInfo");UsernamePasswordToken userToken = (UsernamePasswordToken) token;//2.根据页面提交的用户名userName查询数据库LambdaQueryWrapper<Users> lqw = new LambdaQueryWrapper<>(); //条件对象lqw.eq(Users::getUserId, userToken.getUsername()); //判断数据库里是否有相同的用户名Users user = usersService.getOne(lqw); //数据库查询出来的user对象//比较用户帐号userIdif (user == null) { //return null; //抛出异常 UnknownAccountException}/*** 密码认证,shiro做,* 第一个参数:用户账号(userID)这个地方参数,在授权的时候,可以通过subject.getPrincipal()取出这个信息* 第二个参数:数据库的安全密码* 第三个参数:realmName*/return new SimpleAuthenticationInfo(user.getId(), user.getPassword(), "userRealm");}
}
<a name="FalJo"></a>### 2.配置ShiroConfig类这个里面可以设置哪些访问是需要权限认证的```javapackage com.tj.reggie.config;import org.apache.shiro.authc.credential.HashedCredentialsMatcher;import org.apache.shiro.spring.web.ShiroFilterFactoryBean;import org.apache.shiro.web.mgt.DefaultWebSecurityManager;import org.springframework.beans.factory.annotation.Qualifier;import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.Configuration;import java.util.HashMap;import java.util.Map;@Configurationpublic class ShiroConfig {//加密匹配器,加密规则在这个里面指定@Bean(name = "matcher")public HashedCredentialsMatcher getHashedCredentialsMatcher() {HashedCredentialsMatcher matcher = new HashedCredentialsMatcher();//matcher就是用来指定加密规则SHA-256,也可以使用MD5matcher.setHashAlgorithmName("SHA-256");//hash加密次数matcher.setHashIterations(1);return matcher;}//创建realm对象,需要自定义类@Bean(name = "userRealm")public UserRealm userRealm(HashedCredentialsMatcher matcher) {UserRealm userRealm = new UserRealm();userRealm.setCredentialsMatcher(matcher);return userRealm;}// public IniRealm iniRealm() {// IniRealm iniRealm = new IniRealm("classpath:shiro.ini");// return iniRealm;// }//安全对象@Bean(name = "defaultWebSecurityManager")public DefaultWebSecurityManager getDefaultWebSecurityManager(@Qualifier("userRealm") UserRealm userRealm) {DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();//securityManager要完成校验,需要关联realmsecurityManager.setRealm(userRealm);return securityManager;}//Shiro过滤器@Bean(name = "shiroFilterFactoryBean")public ShiroFilterFactoryBean shiroFilter(@Qualifier("defaultWebSecurityManager") DefaultWebSecurityManager securityManager) {ShiroFilterFactoryBean filter = new ShiroFilterFactoryBean();//过滤器就是shiro权限校验的核心,进行认证和授权是需要securityManager的//设置安全管理器filter.setSecurityManager(securityManager);/*** 设置shiro的拦截规则* anon 匿名用户可访问(常用)* authc 认证用户可访问(常用)* user 使用RemeberMe的用户可访问* perms 拥有对某个资源的权限才可访问* role 对应的角色可访问*/Map<String, String> filterMap = new HashMap<>();filterMap.put("/", "anon");//"/"表示项目根路径不拦截filterMap.put("/login.html", "anon");//表示/login.html不拦截filterMap.put("/users/login", "anon");//表示/users/login不拦截filterMap.put("/users/logout", "anon");//表示/users/logout不拦截filterMap.put("/**", "authc");//表示除了之前的,都需要认证filter.setFilterChainDefinitionMap(filterMap);// 默认的登录页面(如果不设置,会默认/login.jsp)filter.setLoginUrl("/login.html");// 授权未通过的话,会跳转到这个页面filter.setUnauthorizedUrl("/login.html");return filter;}}
3.login的API接口编写
/**
* 用户登录
*
* @param request
* @param users
* @return
*/
@PostMapping("/login")
public R<String> login(HttpServletRequest request, Users users) {
//1.将页面提交的密码password进行md5加密处理
String userId = users.getUserId(); //用户账号
String password = users.getPassword(); //用户密码
/**
* shiro登录验证
*/
//获取当前的subject(可理解为用户)
Subject subject = SecurityUtils.getSubject();
// 封装用户的登录数据token
UsernamePasswordToken token = new UsernamePasswordToken(userId, password);
//执行登录的方法,如果没有异常就说明登录成功
try {
subject.login(token);
return R.success(token.toString());
} catch (UnknownAccountException e) {
return R.error("用户名不存在");
} catch (IncorrectCredentialsException e) {
return R.error("密码不正确");
}
}
4.Shiro退出登录的方法
/**
* 用户退出登录
*
* @param request
* @return
*/
@PostMapping("/logout")
public R<String> logout(HttpServletRequest request) {
//清理Session中保存的当前登录员工的id
// request.getSession().removeAttribute("users");
//shiro的方式退出登录
Subject subject = SecurityUtils.getSubject();
if (subject.isAuthenticated()) {
subject.logout();
}
return R.success("退出成功!");
}
优化:shiro使用token认证
参考:https://blog.csdn.net/forlinkext/article/details/116749697
在resource目录下创建名为shiro.ini的文件
