核心API:
- Subject:用户主体(把操作交给SecurityManager)
- SecurityManager:安全管理器(关联Realm)
- Realm:Shiro连接数据的桥梁(从数据库中获取数据)
Shiro内置过滤器:
- anon:无需认证(登录)可以访问
- authc:必须认证才可以访问
- user:如果使用RememberMe的功能可以直接访问
- perms:该资源必须得到资源权限才可以访问
- role:该资源必须得到角色权限才可以访问
Shiro配置文件:
@Configuration
public class ShiroConfig {
/**
* 创建ShiroFilterFactoryBean
*/
@Bean
public ShiroFilterFactoryBean getShiroFilterFactoryBean(@Qualifier("defaultWebSecurityManager") DefaultWebSecurityManager defaultWebSecurityManager){
ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
//设置安全管理器
shiroFilterFactoryBean.setSecurityManager(defaultWebSecurityManager);
//添加Shiro过滤器
Map<String,String> map = new LinkedHashMap<>();
//添加授权信息,为每个请求地址设置访问权限
//perms后括号内的参数设置:为该请求设置一个名称,后期将权限名称保存在数据库中,通过查询用户是否有这些名称来判断用户是否拥有此类权限
map.put("/","anon");
map.put("/index","authc");
map.put("/delDepart","perms[depart:del]");
map.put("/editDepart","perms[depart:edit]");
map.put("/addDepart","perms[depart:add]");
map.put("/delUser","perms[user:del]");
map.put("/editUser","perms[user:edit]");
//设置未授权跳转页面
shiroFilterFactoryBean.setUnauthorizedUrl("/noPerm");
//设置未登录跳转页面
shiroFilterFactoryBean.setLoginUrl("/");
shiroFilterFactoryBean.setFilterChainDefinitionMap(map);
return shiroFilterFactoryBean;
}
/**
* 创建DefaultWebSecurityManager安全管理器
*/
@Bean(name = "defaultWebSecurityManager")
public DefaultWebSecurityManager getDefaultWebSecurityManager(@Qualifier("userRealm") UserRealm userRealm){
DefaultWebSecurityManager defaultWebSecurityManager = new DefaultWebSecurityManager();
//关联Reaml
defaultWebSecurityManager.setRealm(userRealm);
return defaultWebSecurityManager;
}
/**
* 创建Realm
*/
@Bean(name = "userRealm")
public UserRealm getReaml(){
return new UserRealm();
}
}
Realm实现(授权与身份认证):
//Realm:用于连接数据
public class UserRealm extends AuthorizingRealm {
//用户service
@Autowired
UserService userService;
//角色service
@Autowired
RoleService roleService;
//用户权限service
@Autowired
RolePermService rolePermService;
/**
* 重写执行授权逻辑的方法
* @param principalCollection
* @return
*/
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
System.out.println("执行授权逻辑!");
//给资源进行授权
SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
//创建一个用户主体,来获取登录的用户信息
Subject subject = SecurityUtils.getSubject();
//user对象是通过楼下认证逻辑方法中SimpleAuthenticationInfo传递的
Users user1 = (Users) subject.getPrincipal();
//通过获取到的用户对象,使用用户对象中的角色id去用户权限表(rolePerm)中或获取该角色的权限
List<String> list = new ArrayList<>();
list = rolePermService.findAllPermCode(user1.getRole_id());
//添加资源的授权字段,此时该用户以及完成被授权的所有操作
info.addStringPermissions(list);
return info;
}
/**
* 重写执行认证逻辑的方法:主要用来做用户登录认证
* @param authenticationToken
* @return
* @throws AuthenticationException
*/
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
System.out.println("执行认证逻辑!");
//编写shiro判断逻辑,验证用户名和密码
//判断用户名(通过controller层发送过来的用户token中封装的用户的账号密码)
UsernamePasswordToken token = (UsernamePasswordToken)authenticationToken;
Users user = new Users();
user = userService.findUserByName(token.getUsername());
if (user==null){
return null;//shiro底层会抛出UnknownAccountException
}
//判断密码,第一个参数:传一个user对象给楼上授权逻辑的subject.getPrincipal();第二个参数:获取数据库中的密码,与传来的token中的密码对比;第三个参数:getName() 当前的realm名,可不写
return new SimpleAuthenticationInfo(user,user.getPassword(),"");
}
}
Shiro登录(Controller):
@RequestMapping("/doLogin")
public String doLogin(String username, String password, HttpServletRequest request){
/**
* Shrio认证
*/
//1、获取Subject
Subject subject = SecurityUtils.getSubject();
//2、封装用户数据
UsernamePasswordToken token = new UsernamePasswordToken(username,password);
//3、执行登录方法
try{
//登录验证,会去找Reaml的doGetAuthenticationInfo进行逻辑认证
subject.login(token);
//验证成功跳转到index
return "redirect:/index";
}catch (UnknownAccountException e){
//UnknownAccountException:用户名找不到异常,return到登录页面
return "redirect:/";
}catch (IncorrectCredentialsException e){
//IncorrectCredentialsException:密码错误异常,return到登录页面
return "redirect:/";
}
}
Shiro与Thymeleaf整合:
依赖:
<!-- thymeleaf对shiro的扩展坐标 -->
<dependency>
<groupId>com.github.theborakompanioni</groupId>
<artifactId>thymeleaf-extras-shiro</artifactId>
<version>2.0.0</version>
</dependency>
Shiro配置文件:
//需要在shiro配置文件中增加一个方法,用于thymeleaf和shiro标签配合使用
public ShrioDialect getShiroDialect(){
return new ShiroDialect();
}
前端页面:
shiro:hasPermission 作用:
用于判断用户是否拥有这个权限,有则显示这个div,没有则不显示。
<div shiro:hasPermission="user:add">
进入用户添加功能:<a href="add">用户添加</a><br/>
</div>