1.创建一个简单的Springboot项目,包含shiro和mybatis-plus。
2.集成shiro
2.1引入依赖
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-spring-boot-web-starter</artifactId>
<version>1.4.1</version>
</dependency>
2.2 将shiro主要的类对象交给spring容器,生成自定义Realm实现类Bean。再生成ShiroFilterChainDefinition对象,并配置所要过滤的请求。anon:就是不处理,针对于静态资源和能直接访问的资源;logout:登出路径,它自己有路径并导到指定实现;user:就是需要登陆验证,进入Realm验证。
yml配置:shiro.loginUrl=/login.html
@Bean
public Realm shiroRealm() {
return new ShiroRealm();
}
@Bean
public ShiroFilterChainDefinition shiroFilterChainDefinition(){
DefaultShiroFilterChainDefinition dsfc = new DefaultShiroFilterChainDefinition();
//过滤请求
dsfc.addPathDefinition("/","anon");
dsfc.addPathDefinition("/login","anon");
dsfc.addPathDefinition("/css/**","anon");
dsfc.addPathDefinition("/js/**","anon");
dsfc.addPathDefinition("/images/**","anon");
dsfc.addPathDefinition("/fonts/**","anon");
dsfc.addPathDefinition("/html/**","anon");
//登出
dsfc.addPathDefinition("/logout","logout");
//其他则需要验证
dsfc.addPathDefinition("/**","user");
return dsfc;
}
3.如图可得 主要目标是实现Realm,自己的代码通过调用subject来整体调用。
4.Realm实现代码(思路:登录认证【验证账号密码】,获取权限【拿着用户id,找角色id,再通过角色id集拿权限】)
记忆点:两个方法有先后顺序,先认证authc,再授权authz
String principal = (String) token.getPrincipal();获取用户名
SimpleAuthenticationInfo simpleAuthentication =
newSimpleAuthenticationInfo(users.get(0),users.get(0).getPwd(),this.getName());进行认证(比对密码,若有加密则看注释代码)。
获取权限:数据库中通过RBAC实现的表。查找数据,获取对应的值。
SimpleAuthorizationInfo sim = new SimpleAuthorizationInfo();
sim.setRoles(rolesnames); //对subject设置角色
sim.setStringPermissions(new HashSet<>(premits)); //对subject设置权限
返回sim对象
@Slf4j
public class ShiroRealm extends AuthorizingRealm {
@Resource
private UsersMapper usersMpaper;
@Resource
private RoleMapper roleMapper;
@Resource
private PremitMapper premitMapper;
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
Users user = (Users) principalCollection.getPrimaryPrincipal();
//获取角色id和角色名称
List<Role> roles = roleMapper.getRidByUserId(user.getId());
Set<String> rolesnames = roles.stream().map(v -> v.getRoleName()).collect(Collectors.toSet());
log.info("rolesnames:{}",rolesnames);
//获取角色权限
List<String> premits = premitMapper.getPremitNamesByRoleIds(roles);
log.info("premits:{}",premits);
SimpleAuthorizationInfo sim = new SimpleAuthorizationInfo();
sim.setRoles(rolesnames);
sim.setStringPermissions(new HashSet<>(premits));
return sim;
}
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
String principal = (String) token.getPrincipal();
QueryWrapper<Users> qw = new QueryWrapper<Users>();
qw.eq("username",principal);
List<Users> users = usersMpaper.selectList(qw);
if(users.size()!=0){
SimpleAuthenticationInfo simpleAuthentication = new SimpleAuthenticationInfo(users.get(0),users.get(0).getPwd(),this.getName());
//MD5加密,盐
//new SimpleAuthenticationInfo(username,pwd,ByteSource.Util.bytes(salt),this.getName());
return simpleAuthentication;
}
return null;
}
}
查询的sql
SELECT r.id,r.role_name from users u join users_role ur on ur.users_id = u.id join role r on ur.role_id = r.id where u.id=#{userid}
SELECT p.pre_names from role_premit rp join premit p on rp.premit_id = p.id where rp.role_id in
<foreach collection="roles" item="r" separator="," open="(" close=")">
#{r.id}
</foreach>
整合的总体思路如图
结束。