目录Springboot-cli 开发脚手架系列简介前言1. 环境2. 简介3. Realm配置4. 核心配置5. 接口编写6. 网页资源7. 效果演示8. 源码分享
Springboot-cli 开发脚手架系列
Springboot优雅的整合
shiro
进行登录校验,权限认证(附源码下载)
简介
Springboo配置Shiro进行登录校验,权限认证,附demo演示。
前言
我们致力于让开发者快速搭建基础环境并让应用跑起来,提供使用示例供使用者参考,让初学者快速上手。
本博客项目源码地址:
项目源码github地址
项目源码国内gitee地址
1. 环境
依赖
org.apache.shiro
shiro-core
1.9.0
org.apache.shiro
shiro-spring
1.9.0
com.github.theborakompanioni
thymeleaf-extras-shiro
2.1.0
org.springframework.boot
spring-boot-starter-thymeleaf
yml配置
server: port: 9999 servlet: session: # 让Tomcat只能从COOKIE中获取会话信息,这样,当没有Cookie时,URL也就不会被自动添加上 ;jsessionid=… 了。 tracking-modes: COOKIE
spring: thymeleaf: # 关闭页面缓存,便于开发环境测试 cache: false # 静态资源路径 prefix: classpath:/templates/ # 网页资源默认.html结尾 mode: HTML
2. 简介
Shiro三大功能模块
Subject
认证主体,通常指
用户
(把操做交给SecurityManager)。
SecurityManager
安全管理器,安全管理器,管理全部Subject,能够配合内部安全组件(关联Realm)
Realm
域对象,用于进行权限信息的验证,shiro连接数据的桥梁,如我们的登录校验,权限校验就在Realm进行定义。
3. Realm配置
定义用户实体User ,可根据自己的业务自行定义
@Data
@Accessors(chain = true)
public class User {
/**
* 用户id
*/
private Long userId;
/**
* 用户名
*/
private
String
username;
/**
* 密码
*/
private String password;
/**
* 用户别称
*/
private String name;
}
重写AuthorizingRealm 中登录校验doGetAuthenticationInfo及授权doGetAuthorizationInfo方CaHqx法,编写我们自定义的校验逻辑。
/**
* 自定义登录授权
*
* @author ding
*/
public class UserRealm extends AuthorizingRealm {
/**
* 授权
* 此处权限授予
*/
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
// 在这里为每一个用户添加vip权限
info.addStringPermission("vip");
return info;
}
/**
* 认证
* 此处实现我们的登录逻辑,如账号密码验证
*/
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
// 获取到token
UsernamePasswordToken token = (UsernamePasswordToken) authenticationToken;
// 从token中获取到用户名和密码
String username = token.getUsername();
String password = String.valueOf(token.getPassword());
// 为了方便,这里模拟获取用户
User user = this.getUser();
if (!user.getUsername().equals(username)) {
throw new UnknownAccountException("用户不存在");
} else if (!user.getPassword().equals(password)) {
throw new IncorrectCredentialsException("密码错误");
}
// 校验完成后,此处我们把用户信息返回,便于后面我们通过Subject获取用户的登录信息
return new SimpleAuthenticationInfo(user, password, getName());
}
/**
* 此处模拟用户数据
* 实际开发中,换成数据库查询获取即可
*/
private User getUser() {
return new User()
.setName("admin")
.setUserId(1L)
.setUsername("admin")
.setPassword("123456");
}
}
4. 核心配置
ShiroConfig.java
/**
* Shiro内置过滤器,能够实现拦截器相关的拦截器
* 经常使用的过滤器:
* anon:无需认证(登陆)能够访问
* authc:必须认证才能够访问
* user:若是使用rememberMe的功能能够直接访问
* perms:该资源必须获得资源权限才能够访问,格式 perms[权限1,权限2]
* role:该资源必须获得角色权限才能够访问
**/
/**
* shiro核心管理器
*
* @author ding
*/
@Configuration
public class ShiroConfig {
/**
* 无需认证就可以访问
*/
private final static String ANON = "anon";
/**
* 必须认证了才能访问
*/
private final static String AUTHC = "authc";
/**
* 拥有对某个资源的权限才能访问
*/
private final static String PERMS = "perms";
/**
* 创建realm,这里返回我们上一把定义的UserRealm
*/
@Bean(name = "userRealm")
public UserRealm userRealm() {
return new UserRealm();
}
/**
* 创建安全管理器
*/
@Bean(name = "securityManager")
public DefaultWebSecurityManager getDefaultWebSecurityManager(@Qualifier("userRealm") UserRealm userRealm) {
DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
//绑定realm对象
securityManager.setRealm(userRealm);
return securityManager;
}
/**
* 授权过滤器
*/
@Bean
public ShiroFilterFactoryBean getShiroFilterFactoryBean(@Qualifier("securityManager") DefaultWebSecurityManager defaultWebSecurityManager) {
ShiroFilterFactoryBean bean = new ShiroFilterFactoryBean();
// 设置安全管理器
bean.setSecurityManager(defaultWebSecurityManager);
// 添加shiro的内置过滤器
Map
filterMap = new LinkedHashMap<>();
filterMap.put("/index", ANON);
filterMap.put("/userInfo", PERMS + "[vip]");
filterMap.put("/table2", AUTHC);
filterMap.put("/table3", PERMS + "[vip2]");
bean.setFilterChainDefinitionMap(filterMap);
// 设置跳转登陆页
bean.setLoginUrl("/login");
// 无权限跳转
bean.setUnauthorizedUrl("/unAuth");
return bean;
}
/**
* Thymeleaf中使用Shiro标签
*/
@Bean
public ShiroDialect shiroDialect() {
return new ShiroDialect();
}
}
5. 接口编写
IndexController.java
/**
* @author ding
*/
@Controller
public class IndexController {
@RequestMapping({"/", "/index"})
public String index(Model model) {
model.addAttribute("msg", "hello,shiro");
return "/index";
}
@RequestMapping("/userInfo")
public String table1(Model model) {
return "userInfo";
}
@RequestMapping("/table")
public String table(Model model) {
return "table";
}
@GetMapping("/login")
public String login() {
return "login";
}
@PostMapping(value = "/doLogin")
public String doLogin(@RequestParam("username") String username, @RequestParam("password") String password, Model model) {
//获取当前的用户
Subject subject = SecurityUtils.getSubject();
//用来存放错误信息
String msg = "";
//如果未认证
if (!subject.isAuthenticated()) {
//将用户名和密码封装到shiro中
UsernamePasswordToken token = new UsernamePasswordToken(username, password);
try {
// 执行登陆方法
subject.login(token);
} catch (Exception e) {
e.printStackTrace();
msg = "账号或密码错误";
}
//如果msg为空,说明没有异常,就返回到主页
if (msg.isEmpty()) {
return "redirect:/index";
} else {
model.addAttribute("errorMsg", msg);
return "login";
}
}
return "/login";
}
@GetMapping("/logout")
public String logout() {
SecurityUtils.getSubject().logout();
return "index";
}
@GetMapping("/unAuth")
public String unAuth() {
return "unAuth";
}
}
6. 网页资源
在resources中创建templates文件夹存放页面资源
index.html
用户已登录
用户未登录
用户信息
table
login.html
userInfo.html
用户名:
用户完整信息:
table.hetml
7. 效果演示
启动项目浏览器输入127.0.0.1:9999
当我们点击用户信息和table时会自动跳转登录页面
登录成功后
获取用户信息
此处获取的就是我们就是我们前面doGetAuthenticationInfo方法返回的用户信息,这里为了演示就全部返回了,实际生产中密码是不能返回的。
8. 源码分享
本项目已收录
Springboot-cli开发脚手架,集合各种常用框架使用案例,完善的文档,致力于让开发者快速搭建基础环境并让应用跑起来,并提供丰富的使用示例供使用者参考,帮助初学者快速上手。
项目源码github地址
项目源码国内gitee地址