Subject方法:
getSession()
isAuthenticated() 是否已经登录
login()
logout()
getPrincipal() 获取标识信息:用户名,邮箱,
hasRole() 是否具有某个角色
hasPermisson() 是否具有某个权限
获取Subject:
SecurityUtils.getSubject()
SecurityManager属性
Authenticator
认证器
Authorizer
授权器
认证策略:
ModularRealmAuthenticator
的setAuthenticationStrategy()
方法中配置认证策略
shiro有三种认证策略:
- AllSuccessfulStrategy
- AtLeastOneSuccessfulStrategy
- FirstSuccessfulStrategy
实体类:
@Data
@AllArgsConstructor
public class User {
private String id;
private String username;
private String password;
private HashSet<Role> roles;
}
@Data
@AllArgsConstructor
public class Role {
private String id;
private String roleName;
private Set<Permission> permissions;
}
@Data
@AllArgsConstructor
public class Permission {
private String id;
private String permissionName;
}
LoginService模仿从数据库中获取的数据:
@Service
public class LoginServiceImpl implements LoginService{
@Override
public User getUserByName(String username) {
return getMapByName(username);
}
public User getMapByName(String username){
Permission permission1 = new Permission("1", "query");
Permission permission2 = new Permission("2", "add");
HashSet<Permission> permissionSet = new HashSet<>();
permissionSet.add(permission1);
permissionSet.add(permission2);
Role role = new Role("!", "admin", permissionSet);
HashSet<Role> roleSet = new HashSet<>();
roleSet.add(role);
User user = new User("1", "cc", "123", roleSet);
HashMap<String, User> map = new HashMap<>();
map.put(user.getUsername(),user);
// 权限2
HashSet<Permission> permissionSet2 = new HashSet<>();
// query
permissionSet2.add(permission1);
// 角色2
Role role2 = new Role("2", "user", permissionSet2);
HashSet<Role> roleSet2 = new HashSet<>();
roleSet2.add(role2);
// 只读 user
User user1 = new User("2", "zs", "123", roleSet2);
map.put(user1.getUsername(),user1);
return map.get(username);
}
}
realms:
@Component
public class CustomRealm extends AuthorizingRealm {
@Autowired
LoginService loginService;
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
// 获取登录用户名
String name = principals.getPrimaryPrincipal().toString();
User user = loginService.getUserByName(name);
if(user == null){
return null;
}
SimpleAuthorizationInfo simpleAuthorizationInfo = new SimpleAuthorizationInfo();
for (Role role : user.getRoles()) {
simpleAuthorizationInfo.addRole(role.getRoleName());
for (Permission permission : role.getPermissions()) {
simpleAuthorizationInfo.addStringPermission(permission.getPermissionName());
}
}
// 返回这个角色 具有的权限信息
return simpleAuthorizationInfo;
}
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
if(StringUtils.isEmpty(token.getPrincipal())){
return null;
}
// 获取用户信息
String name = token.getPrincipal().toString();
User user = loginService.getUserByName(name);
if(user == null){
// 这里返回后会报出对应的异常
return null;
}else{
// 返回数据库 查出来的信息
SimpleAuthenticationInfo simpleAuthenticationInfo = new SimpleAuthenticationInfo(name, user.getPassword(), this.getName());
// 返回这个角色 具有的认证信息
return simpleAuthenticationInfo;
}
}
}
@Component
public class Realm01 extends AuthorizingRealm {
/**
* 这个Realm 不做认证工作,,单纯只是为了测试 认证策略
* @param token
* @return
* @throws AuthenticationException
*/
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
// 输入什么 返回什么,怎么都成功
return new SimpleAuthenticationInfo(token.getPrincipal(),token.getCredentials(),getName());
}
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
return null;
}
}
shiro配置文件: securityManager
配置多realm下的认证策略,,,ShiroFilterFactoryBean
工厂配置过滤条件:
@Configuration
public class ShiroConfig {
@Autowired
CustomRealm customRealm;
@Autowired
Realm01 realm01;
@Bean
public DefaultWebSecurityManager defaultWebSecurityManager(){
DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
// securityManager.setRealm(customRealm);
// 同时返回所有 登录成功realm信息
AtLeastOneSuccessfulStrategy atLeastOneSuccessfulStrategy = new AtLeastOneSuccessfulStrategy();
// 只返回第一个 认证成功的realm信息,,即使已经有 realm 认证成功了,还是会去继续调用后面剩下的Realm 进行认证操作
FirstSuccessfulStrategy firstSuccessfulStrategy = new FirstSuccessfulStrategy();
// 所有成功
AllSuccessfulStrategy allSuccessfulStrategy = new AllSuccessfulStrategy();
ModularRealmAuthenticator authenticator = new ModularRealmAuthenticator();
securityManager.setAuthenticator(authenticator);
authenticator.setAuthenticationStrategy(atLeastOneSuccessfulStrategy);
ArrayList<Realm> realms = new ArrayList<>();
realms.add(realm01);
realms.add(customRealm);
securityManager.setRealms(realms);
return securityManager;
}
// filter工厂,,设置对应的过滤条件和跳转条件
@Bean
public ShiroFilterFactoryBean shiroFilterFactoryBean(){
ShiroFilterFactoryBean bean = new ShiroFilterFactoryBean();
// 设置安全管理器
bean.setSecurityManager(defaultWebSecurityManager());
/**
* 添加shiro 内置过滤器
* anon 匿名
* authc 认证了
* users 必须拥有记住我 功能 才能访问
* perms: 拥有对某个资源的权限才能访问
* role: 拥有某个角色权限
*/
HashMap<String, String> filterMap = new HashMap<>();
// 登出
filterMap.put("logout","logout");
filterMap.put("/**","authc");
// 访问不了的时候,跳转到登录页面
bean.setLoginUrl("/doLogin");
// 登录成功
bean.setSuccessUrl("/index");
bean.setFilterChainDefinitionMap(filterMap);
return bean;
}
/**
* 开启 shiro aop 注解支持,否则 @RequiresRoles 等注解无法生效
* @return
*/
@Bean
public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(){
AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor = new AuthorizationAttributeSourceAdvisor();
authorizationAttributeSourceAdvisor.setSecurityManager(defaultWebSecurityManager());
return authorizationAttributeSourceAdvisor;
}
/**
* 开启 shiro aop 注解支持,否则 @RequiresRoles 等注解无法生效,,,这个不写@RequirePermission生效,@RequiresRoles不生效
* @return
*/
@Bean
public DefaultAdvisorAutoProxyCreator advisorAutoProxyCreator(){
DefaultAdvisorAutoProxyCreator advisorAutoProxyCreator = new DefaultAdvisorAutoProxyCreator();
advisorAutoProxyCreator.setProxyTargetClass(true);
return advisorAutoProxyCreator;
}
}
@ControllerAdvice
public class GlobalExceptionHandler {
@ExceptionHandler
@ResponseBody
public String ErrorHandler(AuthorizationException e){
System.out.println("没有权限"+e.getMessage());
return "no permission";
}
}
controller:
@RestController
public class LoginController {
@PostMapping("/doLogin")
public String login(String username, String password, Model model){
Subject subject = SecurityUtils.getSubject();
UsernamePasswordToken token = new UsernamePasswordToken(username, password);
try {
subject.login(token);
// subject.checkRole("admin");
// subject.checkPermissions("query","add");
// 获取登录成功的用户信息
// 如果是多个
PrincipalCollection principals = subject.getPrincipals();
List list = principals.asList();
System.out.println(list);
for (Object o : list) {
System.out.println(o.getClass()+"=======>"+o);
}
return "login success";
} catch (UnknownAccountException e) {
return "unknown account";
}catch (IncorrectCredentialsException e){
return "incorrect credentials";
}catch (AuthorizationException e){
return "no authorization";
}
}
@GetMapping("/logout")
public String logout(){
Subject subject = SecurityUtils.getSubject();
subject.logout();
return "logout";
}
@RequiresRoles("admin")
@GetMapping("/hello")
public String hello(){
return "hello";
}
@RequiresPermissions("query")
@GetMapping("/index")
public String index(){
return "index";
}
@RequiresPermissions("add")
@GetMapping("/add")
public String add(){
Subject subject = SecurityUtils.getSubject();
subject.checkPermission("add");
return "add success";
}
}
认证异常
授权异常
4. AuthorizationException
No realms have been configured! One or more realms must be present to execute an authorization operation.
解决: shiro必须先设置 认证器
,再进行 realm 设置
引用: https://blog.csdn.net/sword_anyone/article/details/117852515
@RequiresRoles不起作用
在springboot中配置shiro,,结果@RequiresRoles
,,@RequiresPermission
等注解都无效
解决:
在shiro的配置文件中,注入 开启 支持aop,代理的bean:
@Configuration
public class ShiroConfiguration {
/**
* 开启shiro aop注解支持.否则@RequiresRoles等注解无法生效
* 使用代理方式;
* @param securityManager
* @return
*/
@Bean
public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(SecurityManager securityManager){
AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor = new AuthorizationAttributeSourceAdvisor();
authorizationAttributeSourceAdvisor.setSecurityManager(securityManager);
return authorizationAttributeSourceAdvisor;
}
/**
* 自动创建代理
* @return
*/
@Bean
@DependsOn({"lifecycleBeanPostProcessor"})
public DefaultAdvisorAutoProxyCreator advisorAutoProxyCreator(){
DefaultAdvisorAutoProxyCreator advisorAutoProxyCreator = new DefaultAdvisorAutoProxyCreator();
advisorAutoProxyCreator.setProxyTargetClass(true);
return advisorAutoProxyCreator;
}
}
引用: http://www.wjhsh.net/expiator-p-8621847.html
git:https://github.com/water-kid/code/tree/master/shiro_springboot
引用:
https://blog.csdn.net/w399038956/article/details/120434244
http://t.zoukankan.com/learnhow-p-10090718.html