Apache Shiro 是一个功能强大且易于使用的 Java 安全(权限)框架。Shiro 可以完成:认证、授权、加密、会话管理、与 Web 集成、缓存 等。借助 Shiro 您可以快速轻松地保护任何应用程序——从最小的移动应用程序到最大的 Web 和企业应用程序。
官方网址: https://shiro.apache.org/
引入依赖
<dependency>
<groupId>org.apache.shirogroupId>
<artifactId>shiro-spring-boot-web-starterartifactId>
<version>1.9.0version>
dependency>
指定登录路径
shiro:
loginUrl: /user/login
创建数据库
user表
role表
user_role表
permissions表
role_permissions表
省略Mybatis查询数据库代码
@Component("authorizer")
public class MyRealm extends AuthorizingRealm {
@Autowired
private UserService userService;
/**
* 自定义授权方法
* @param principalCollection
* @return
*/
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
//1 创建对象,存储当前登录的用户的权限和角色
SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
//2 获取当前用户身份信息
String name = principalCollection.getPrimaryPrincipal().toString();
List<String> roles = userService.getUserRoles(name);
//3 存储角色
info.addRoles(roles);
//4 获取用户角色的权限信息
List<String> permissions=new ArrayList<>();
for (String role : roles) {
List<String> ps = userService.getUserPermission(role);
permissions.addAll(permissions);
}
//5 存储权限信息
info.addStringPermissions(permissions);
//6 返回
return info;
}
/**
* 自定义登录方法
* @param authenticationToken
* @return
* @throws AuthenticationException
*/
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
//获取用户身份信息
String name = authenticationToken.getPrincipal().toString();
//查询用户信息
User user = userService.getUserByName(name);
if (user!=null){
AuthenticationInfo authenticationInfo = new SimpleAuthenticationInfo(
name,//用户名
user.getPwd(),//密码
ByteSource.Util.bytes("salt"),//加盐字符
getName()//realm名称
);
return authenticationInfo;
}
return null;
}
}
@Configuration
public class ShiroConfig {
//配置自定义Realm
@Bean
public MyRealm myRealm(){
return new MyRealm();
}
//配置 SecurityManager
@Bean
public DefaultWebSecurityManager defaultWebSecurityManager(){
//1 创建 defaultWebSecurityManager 对象
DefaultWebSecurityManager manager = new DefaultWebSecurityManager();
//2 创建加密对象,并设置相关属性
HashedCredentialsMatcher matcher = new HashedCredentialsMatcher();
//2.1 采用 md5 加密
matcher.setHashAlgorithmName("md5");
//2.2 迭代加密次数
matcher.setHashIterations(3);
//3 将加密对象存储到 myRealm 中
myRealm().setCredentialsMatcher(matcher);
//4 将 myRealm 存入 defaultWebSecurityManager 对象
manager.setRealm(myRealm());
//5 返回 defaultWebSecurityManager 对象
return manager;
}
//配置 Shiro 内置过滤器拦截范围
@Bean
public DefaultShiroFilterChainDefinition shiroFilterChainDefinition(){
DefaultShiroFilterChainDefinition definition = new DefaultShiroFilterChainDefinition();
//设置不认证可以访问的资源
definition.addPathDefinition("/user/login","anon");
//配置退出过滤器
definition.addPathDefinition("/logout","logout");
//设置需要进行登录认证的拦截范围
definition.addPathDefinition("/**","authc");
return definition;
}
}
@RestController
@RequestMapping("/user")
@ResponseBody
public class UserController {
@PostMapping(path = "/login",produces = "application/json")
public String login(@RequestBody User user){
try {
//1 获取 Subject 对象
Subject subject = SecurityUtils.getSubject();
//2 封装请求数据到 token 对象中
UsernamePasswordToken token = new UsernamePasswordToken(user.getName(),user.getPwd());
subject.login(token);
return "登录成功!";
}
catch (LockedAccountException e){
return "账号封禁";
}
catch (UnknownAccountException e) {
e.printStackTrace();
return "用户不存在";
}
catch (IncorrectCredentialsException e) {
e.printStackTrace();
return "密码错误";
}
catch (AuthenticationException e) {
e.printStackTrace();
return "登录失败!";
}
}
//登录认证验证角色
@RequiresRoles("admin")
@GetMapping("/roles")
public String userLoginRoles() {
return "验证角色成功";
}
//登录认证验证权限
@RequiresPermissions("user:delete")
@GetMapping("/permissions")
public String userLoginPermissions() {
return "验证权限成功";
}
}
@ControllerAdvice
@ResponseBody
public class PermissionsException {
@ExceptionHandler(UnauthorizedException.class)
public String unauthorizedException(Exception ex){
return "无权限";
}
}
AuthenticationStrategy class | 描述 |
---|---|
AtLeastOneSuccessfulStrategy | 只要有一个(或更多)的 Realm 验证成功,那么认证将视为成功 |
FirstSuccessfulStrategy | 第一个 Realm 验证成功,整体认证将视为成功,且后续 Realm 将被忽略 |
AllSuccessfulStrategy | 所有 Realm 成功,认证才视为成功 |
ModularRealmAuthenticator 内置的认证策略默认实现是 AtLeastOneSuccessfulStrategy 方式。
//配置 SecurityManager
@Bean
public DefaultWebSecurityManager defaultWebSecurityManager(){
//1 创建 defaultWebSecurityManager 对象
DefaultWebSecurityManager defaultWebSecurityManager = new
DefaultWebSecurityManager();
//2 创建认证对象,并设置认证策略
ModularRealmAuthenticator modularRealmAuthenticator = new
ModularRealmAuthenticator();
modularRealmAuthenticator.setAuthenticationStrategy(new
AllSuccessfulStrategy());
defaultWebSecurityManager.setAuthenticator(modularRealmAuthenticator);
//3 封装 myRealm 集合
List<Realm> list = new ArrayList<>();
list.add(myRealm1);
list.add(myRealm2);
//4 将 myRealm 存入 defaultWebSecurityManager 对象
defaultWebSecurityManager.setRealms(list);
//5 返回
return defaultWebSecurityManager;
SessionManager由SecurityManager管理。Shiro提供了三种实现:
Session session = SecurityUtils.getSubject().getSession();
session.setAttribute(“key”,”value”)
学习内容来自尚硅谷