SpringBoot集成Shiro
项目目录
配置
shiro.ini
点击查看代码
#
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
#
# =============================================================================
# Quickstart INI Realm configuration
#
# For those that might not understand the references in this file, the
# definitions are all based on the classic Mel Brooks' film "Spaceballs". ;)
# =============================================================================
# -----------------------------------------------------------------------------
# Users and their assigned roles
#
# Each line conforms to the format defined in the
# org.apache.shiro.realm.text.TextConfigurationRealm#setUserDefinitions JavaDoc
# -----------------------------------------------------------------------------
[users]
# user 'root' with password 'secret' and the 'admin' role
root = secret, admin
# user 'guest' with the password 'guest' and the 'guest' role
guest = guest, guest
# user 'presidentskroob' with password '12345' ("That's the same combination on
# my luggage!!!" ;)), and role 'president'
presidentskroob = 12345, president
# user 'darkhelmet' with password 'ludicrousspeed' and roles 'darklord' and 'schwartz'
darkhelmet = ludicrousspeed, darklord, schwartz
# user 'lonestarr' with password 'vespa' and roles 'goodguy' and 'schwartz'
lonestarr = vespa, goodguy, schwartz
# -----------------------------------------------------------------------------
# Roles with assigned permissions
#
# Each line conforms to the format defined in the
# org.apache.shiro.realm.text.TextConfigurationRealm#setRoleDefinitions JavaDoc
# -----------------------------------------------------------------------------
[roles]
# 'admin' role has all permissions, indicated by the wildcard '*'
admin = *
# The 'schwartz' role can do anything (*) with any lightsaber:
schwartz = lightsaber:*
# The 'goodguy' role is allowed to 'drive' (action) the winnebago (type) with
# license plate 'eagle5' (instance specific id)
goodguy = winnebago:drive:eagle5
log4j.properties
点击查看代码
log4j.rootLogger=INFO, stdout
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%d %p [%c] - %m %n
# General Apache libraries
log4j.logger.org.apache=WARN
# Spring
log4j.logger.org.springframework=WARN
# Default Shiro logging
log4j.logger.org.apache.shiro=INFO
# Disable verbose logging
log4j.logger.org.apache.shiro.util.ThreadContext=WARN
log4j.logger.org.apache.shiro.cache.ehcache.EhCache=WARN
依赖
点击查看代码
<!--前端交互整合-->
<dependency>
<groupId>com.github.theborakompanioni</groupId>
<artifactId>thymeleaf-extras-shiro</artifactId>
<version>2.0.0</version>
</dependency>
<!--整合Mybatis-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.1.22</version>
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>2.1.2</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
<!-- shiro-spring -->
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-spring</artifactId>
<version>1.5.3</version>
</dependency>
<!--thymeleaf-->
<dependency>
<groupId>org.thymeleaf</groupId>
<artifactId>thymeleaf-spring5</artifactId>
</dependency>
<dependency>
<groupId>org.thymeleaf.extras</groupId>
<artifactId>thymeleaf-extras-java8time</artifactId>
</dependency>
****
Controller
点击查看代码
@Controller
public class MyController {
@RequestMapping({"/", "/index"})
public String toIndex(Model model) {
model.addAttribute("msg", "首页");
return "index";
}
@RequestMapping("/user/add")
public String addUser() {
return "user/add";
}
@RequestMapping("/user/update")
public String updateUser() {
return "user/update";
}
@RequestMapping("/toLogin")
public String toLogin() {
return "login";
}
@RequestMapping("/login")
public String login(String username, String password, Model model) {
// 获取用户
Subject user = SecurityUtils.getSubject();
// 封装参数,获取token
UsernamePasswordToken token = new UsernamePasswordToken(username, password);
// 验证登录
try {
// 执行登录操作,跨类调用
user.login(token);
model.addAttribute("msg", "成功登录");
return "index";
} catch (UnknownAccountException uae) {
model.addAttribute("msg", "用户名错误");
return "login";
} catch (IncorrectCredentialsException ice) {
model.addAttribute("msg", "用户密码错误");
return "login";
}
}
@RequestMapping("/noAuth")
@ResponseBody
public String noAuth() {
return "未授权,无法访问";
}
}
ShiroConfig
点击查看代码
@Configuration
public class ShiroConfig {
// 3 获取ShiroBean
@Bean
public ShiroFilterFactoryBean getShiroFilterFactoryBean(
@Qualifier("getDefaultWebSecurityManager") WebSecurityManager securityManager
) {
ShiroFilterFactoryBean bean = new ShiroFilterFactoryBean();
// 设置安全管理器
bean.setSecurityManager(securityManager);
// 添加shiro的内置过滤器
/*
anon: 无需认证就可以登录
authc:必须认证才能登录
user: 必须拥有“记住我”这个功能
perms:拥有对某个资源的权限才能访问
role:拥有某个角色才能访问
*/
LinkedHashMap<String, String> map = new LinkedHashMap<>();
// 权限授权,访问url需要权限,支持通配符
map.put("/user/add", "perms[user:add]");
map.put("/user/update", "perms[user:update]");
bean.setFilterChainDefinitionMap(map);
// 设置登录url映射
bean.setLoginUrl("/toLogin");
// 设置未授权的请求
bean.setUnauthorizedUrl("/noAuth");
return bean;
}
// 2 获取安全管理器
@Bean(name = "getDefaultWebSecurityManager")
public DefaultWebSecurityManager getDefaultWebSecurityManager(
@Qualifier("userRealm") UserRealm userRealm) {
DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
// 直接userRealm()传参也可以,这里演示Spring指定自动注入
securityManager.setRealm(userRealm);
return securityManager;
}
// 1 创建realm对象,需要自定义另一个类
@Bean(name = "userRealm")
public UserRealm userRealm() {
return new UserRealm();
}
// 结合Mybatis,整合ShiroDialect进组件
@Bean
public ShiroDialect getShiroDialect(){
return new ShiroDialect();
}
}
userRelam
点击查看代码
// 自定义realms,继承AuthorizingRealm
public class UserRealm extends AuthorizingRealm {
@Autowired
private UserServiceImpl userService;
// 授权
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
// 进入被拦截的url,就会进这个info
SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
// 授权应该从数据库查出权限字段
// info.addStringPermission("user:add");
// 从 new SimpleAuthenticationInfo(queryUser, queryUser.getPwd(), "");传递过来第一个参数user最为subject
Subject subject = SecurityUtils.getSubject();
User currentUser = (User) subject.getPrincipal();
// 从数据库中获取验证权限
info.addStringPermission(currentUser.getPerms());
return info;
}
// 用户认证
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
// 模拟数据库中查出用户名、密码
UsernamePasswordToken userToken = (UsernamePasswordToken) token;
User currentUser = userService.queryUserByName(userToken.getUsername());
// 验证用户名
if (currentUser == null) {
// 用户名不正确,就抛出UnknownAccountException
return null;
}
// 密码验证,shiro完成,不需要用户判断.直接返回
return new SimpleAuthenticationInfo(currentUser, currentUser.getPwd(), "");
}
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构
· 字符编码:从基础到乱码解决