转载

SpringBoot 2.0 开发案例之整合Shiro安全框架

点击▲关注 “ 爪哇笔记 ”   给公众号标星置顶

更多精彩 第一时间直达

SpringBoot 2.0 开发案例之整合Shiro安全框架

一、前言

为了管理撸主的小黄图,特别安排了一个后台管理系统,权限管理当然是首选  Shiro  了。

二、表设计

至少需要以下几张表,具体如何设计要视自己的业务而定:

  • sys_user: 用户表

  • sys_role: 角色表

  • sys_menu: 菜单表

  • sys_ user_ role: 用户对应角色

  • sys_ role_ menu: 用户对应菜单

三、整合

pom.xml引入:

<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-spring-boot-web-starter</artifactId>
<version>1.4.2</version>
</dependency>

定义 UserRealm

/**
* 用户认证
*/
public class UserRealm extends AuthorizingRealm {
 
@Autowired
private SysUserService userService;
 
/**
* 获取授权
* @param principalCollection
* @return
*/
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
Long userId = ShiroUtils.getUserId();
List<String> rolesSet = userService.listUserRoles(userId);
List<String> permsSet = userService.listUserPerms(userId);
SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
info.setRoles(new HashSet<>(rolesSet));
info.setStringPermissions(new HashSet<>(permsSet));
return info;
}
 
/**
* 获取认证
* @param authenticationToken
* @return
* @throws AuthenticationException
*/
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken)
throws AuthenticationException {
String username = (String) authenticationToken.getPrincipal();
String password = new String((char[]) authenticationToken.getCredentials());
SysUser user = userService.getUser(username);
if (user == null) {
throw new UnknownAccountException("账户不存在");
}
if(!password.equals(user.getPassword())) {
throw new IncorrectCredentialsException("密码不正确");
}
return new SimpleAuthenticationInfo(user, password, getName());
}
}

定义 ShiroConfig

/**
* Shiro权限配置
*/
@Configuration
public class ShiroConfig {
 
@Bean
public UserRealm userRealm() {
return new UserRealm();
}
 
@Bean
public ShiroFilterFactoryBean shiroFilterFactoryBean (SecurityManager securityManager) {
ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
// 必须设置SecuritManager
shiroFilterFactoryBean.setSecurityManager(securityManager);
//设置登录页
shiroFilterFactoryBean.setLoginUrl("/login.shtml");
// 登录成功后要跳转的链接,如果是ajax这里无效
shiroFilterFactoryBean.setSuccessUrl("/index");
// 未授权界面;
shiroFilterFactoryBean.setUnauthorizedUrl("/403");
// 拦截器
Map<String, String> filterChainDefinitionMap = new LinkedHashMap<>();
// 过滤链定义,从上向下顺序执行,一般将 /**放在最为下边
// authc:所有url都必须认证通过才可以访问; anon:所有url都都可以匿名访问
/**
* 静态文件
*/
filterChainDefinitionMap.put("/css/**","anon");
filterChainDefinitionMap.put("/images/**","anon");
filterChainDefinitionMap.put("/js/**","anon");
filterChainDefinitionMap.put("/file/**","anon");
/**
* 登录注册
*/
filterChainDefinitionMap.put("/register.shtml","anon");
filterChainDefinitionMap.put("/login.shtml","anon");
filterChainDefinitionMap.put("/sys/logout","anon");
filterChainDefinitionMap.put("/sys/login","anon");
filterChainDefinitionMap.put("/sys/register","anon");
/**
* 管理后台
*/
filterChainDefinitionMap.put("/sys/**", "roles[admin]");
filterChainDefinitionMap.put("/**", "authc");
shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);
return shiroFilterFactoryBean;
}
 
@Bean
public SessionsSecurityManager securityManager() {
DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
securityManager.setRealm(userRealm());
securityManager.setSessionManager(sessionManager());
return securityManager;
}
@Bean
public DefaultWebSessionManager sessionManager() {
DefaultWebSessionManager sessionManager = new DefaultWebSessionManager();
//去掉小尾巴 JSESSIONID
sessionManager.setSessionIdUrlRewritingEnabled(false);
long time = 2*60*60*1000;
sessionManager.setGlobalSessionTimeout(time);
return sessionManager;
}
}

登录 LoginController

/**
* 登录
*/
@Controller
@RequestMapping("/sys")
public class LoginController {
 
private static final Logger logger = LoggerFactory.getLogger(LoginController.class);
 
@Autowired
private SysUserService sysUserService;
 
/**
* 登录
*/
@PostMapping("/login")
@ResponseBody
public Result login(String username, String password){
logger.info("用户登录");
try{
Subject subject = ShiroUtils.getSubject();
password = MD5Utils.encrypt(username, password);
UsernamePasswordToken token = new UsernamePasswordToken(username, password);
subject.login(token);
}catch (Exception e) {
e.printStackTrace();
return Result.error("登录失败");
}
return Result.ok("登录成功");
}
}

四、过滤器

shiro提供和多个默认的过滤器,我们可以用这些过滤器来配置过滤指定url的访问权限,这里只介绍几个比较常用的。

SpringBoot 2.0 开发案例之整合Shiro安全框架

常用的权限控制注解,可以在控制器类上使用。

SpringBoot 2.0 开发案例之整合Shiro安全框架

五、前端使用

过滤器实现了后端的权限控制访问,那么如何在前端来使用注解实现按钮的显示呢?通常 thymeleaf 是 SpringBoot的标配模板了,这里我们使用第三方插件来实现。

pom.xml 引入:

<dependency>
<groupId>com.github.theborakompanioni</groupId>
<artifactId>thymeleaf-extras-shiro</artifactId>
<version>2.0.0</version>
</dependency>

ShiroConfig 追加以下代码:

@Bean
public ShiroDialect shiroDialect(){
return new ShiroDialect();
}

页面头部引入:

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org"
xmlns:shiro="http://www.pollix.at/thymeleaf/shiro">

页面使用:

<!-- 显示登陆用户昵称 -->
<shiro:principal property="nickname"/>
 
<!-- 游客 -->
<p shiro:guest="">Please <a href="login.html">login</a></p>
 
<!-- 认证通过或已记住的用户。-->
<p shiro:user="">
Welcome back John! Not John? Click <a href="login.html">here</a> to login.
</p>
 
<!-- 已认证通过的用户。不包含已记住的用户,这是与user标签的区别所在。-->
<p shiro:authenticated="">
Hello, <span shiro:principal=""></span>, how are you today?
</p>
 
<a shiro:authenticated="" href="updateAccount.html">Update your contact information</a>
 
<!-- 输出当前用户信息,通常为登录帐号信息。-->
<p>Hello, <shiro:principal/>, how are you today?</p>
 
<!-- 未认证通过用户,与authenticated标签相对应。与guest标签的区别是,该标签包含已记住用户。-->
<p shiro:notAuthenticated="">
Please <a href="login.html">login</a> in order to update your credit card information.
</p>
 
<!-- 验证当前用户是否属于该角色。-->
<a shiro:hasRole="admin" href="admin.html">Administer the system</a><!-- 拥有该角色 -->
 
<!-- 与hasRole标签逻辑相反,当用户不属于该角色时验证通过。-->
<p shiro:lacksRole="developer"><!-- 没有该角色 -->
Sorry, you are not allowed to developer the system.
</p>
 
<!-- 验证当前用户是否属于以下所有角色。-->
<p shiro:hasAllRoles="developer, 2"><!-- 角色与判断 -->
You are a developer and a admin.
</p>
 
<!-- 验证当前用户是否属于以下任意一个角色。-->
<p shiro:hasAnyRoles="admin, vip, developer,1"><!-- 角色或判断 -->
You are a admin, vip, or developer.
</p>
 
<!--验证当前用户是否拥有指定权限。-->
<a shiro:hasPermission="userInfo:add" href="createUser.html">添加用户</a><!-- 拥有权限 -->
 
<!-- 与hasPermission标签逻辑相反,当前用户没有制定权限时,验证通过。-->
<p shiro:lacksPermission="userInfo:del"><!-- 没有权限 -->
Sorry, you are not allowed to delete user accounts.
</p>
 
<!-- 验证当前用户是否拥有以下所有角色。-->
<p shiro:hasAllPermissions="userInfo:view, userInfo:add"><!-- 权限与判断 -->
You can see or add users.
</p>
 
<!-- 验证当前用户是否拥有以下任意一个权限。-->
<p shiro:hasAnyPermissions="userInfo:view, userInfo:del"><!-- 权限或判断 -->
You can see or delete users.
</p>
<a shiro:hasPermission="pp" href="createUser.html">Create a new User</a>

六、小结

SpringBoot 2.0 开发案例之整合Shiro安全框架

SpringBoot 2.0 开发案例之整合Shiro安全框架

小黄图终于有后台了! !!

SpringBoot 2.0 开发案例之整合Shiro安全框架

1 十万爆笑动图上线了

2.  周末,撸一个鉴黄 API 给大家

3.  高速下载小视频神器,墙裂推荐

4.  深夜,给小黄图撸了一件漂亮的外壳

5.  小黄图升级了,接入更加强大的鉴黄功能

6.  深夜,吐血训练了百万小黄图撸了一个图床

SpringBoot 2.0 开发案例之整合Shiro安全框架

▲一个有温度的公众号,期待与你一起进步

原文  http://mp.weixin.qq.com/s?__biz=MzA3OTUyNjkwMw==&mid=2656652866&idx=1&sn=33db3480c81d5f9c0a4c1037e70e10c8
正文到此结束
Loading...