Springboot整合Shiro实现登录与权限校验详细解读

网友投稿 271 2022-08-01


目录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地址


版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:Java8通过CompletableFuture实现异步回调
下一篇:一文带你了解Java中的ForkJoin(浅谈java)
相关文章

 发表评论

暂时没有评论,来抢沙发吧~