Shiro是一个基于Apache研发的Java安全框架
三个核心组件:Subject, SecurityManager 和 Realms.
Subject表示当前操作用户
SecurityManager Shiro框架的核心
Realms桥接器
实现思路:
一.导入依赖
关键依赖:shiro包和thymeleaf包
<!--shiro-->
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-spring</artifactId>
<version>1.7.1</version>
</dependency>
<!--thymeleaef-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
二:数据库和Service层
创建user用户表,
字段:username用户名,password密码,perms权限,role角色
UserMapper接口继承BaseMapper类
@Mapper
public interface UserMapper extends BaseMapper<User> {
}
@Service
public class UserServiceImpl implements userService {
@Autowired
UserMapper userMapper;
@Override
public User getUser(String username) {
QueryWrapper<User> qw=new QueryWrapper<>();
qw.eq("username",username);
return userMapper.selectOne(qw);
}
}
编写getUser()方法在后面用于shiro调用验证信息
三:编写Realm
Realm称之为Shiro与安全数据之间的桥梁,Shiro从Realm中获取认证和授权信息
public class UserRealm extends AuthorizingRealm {
@Autowired
UserServiceImpl userService;
/**
* 授权方法
*
* @param principalCollection
* @return
*/
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
//获取当前登录信息
Subject subject = SecurityUtils.getSubject();
User user = (User) subject.getPrincipal();
//设置角色
Set<String> role = new HashSet<>();
if (user.getRole() == 1) {
role.add("hyq");
} else if (user.getRole() == 2) {
role.add("xqq");
}
SimpleAuthorizationInfo info = new SimpleAuthorizationInfo(role);
//设置权限
info.addStringPermission("所有人");
return info;
}
/**
* 认证身份信息
*
* @param authenticationToken
* @return
* @throws AuthenticationException
*/
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
//拿到token令牌
UsernamePasswordToken token = (UsernamePasswordToken) authenticationToken;
//根据前端传来的token验证信息
User user = userService.getUser(token.getUsername());
//若不为空则交给AuthenticationInfo
if (user != null) {
return new SimpleAuthenticationInfo(user, user.getPassword(), getName());
}
return null;
}
}
继承AuthorizingRealm类,重写授权和验证的方法
记住用户是先认证,然后授权
四:编写Springboot的Shiro配置类
@Configuration
public class UserShiro {
/**
* shiro过滤器工厂
*
* @param defaultWebSecurityManager
* @return
*/
@Bean
public ShiroFilterFactoryBean shiroFilterFactoryBean(@Qualifier("defaultWebSecurityManager") DefaultWebSecurityManager defaultWebSecurityManager) {
//创建一个Shiro权限的过滤器
ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
//设置过滤器的安全管理器
shiroFilterFactoryBean.setSecurityManager(defaultWebSecurityManager);
//设置map的权限角色设置信息
Map<String, String> map = new HashMap<>();
map.put("/index", "authc");
map.put("/", "authc");
map.put("/one", "roles[xqq]");
map.put("/tow","perms[所有人]");
//把map的权限信息注入到过滤器中
shiroFilterFactoryBean.setFilterChainDefinitionMap(map);
shiroFilterFactoryBean.setLoginUrl("/login");//设置登录页面
shiroFilterFactoryBean.setUnauthorizedUrl("/unau");//设置无权限操作页面
return shiroFilterFactoryBean;
}
/**
* 默认的web安全管理器
*
* @param userRealm 域对象
* @return 返回安全管理器
*/
@Bean
public DefaultWebSecurityManager defaultWebSecurityManager(@Qualifier("getRealm") UserRealm userRealm) {
//创建一个默认的安全管理器
DefaultWebSecurityManager defaultWebSecurityManager = new DefaultWebSecurityManager();
//设置安全管理器的域
defaultWebSecurityManager.setRealm(userRealm);
return defaultWebSecurityManager;
}
/**
* 域
*
* @return
*/
@Bean
public UserRealm getRealm() {
return new UserRealm();
}
}
三个非常重要的安全配置:
Realm,DefaultWebSecurityManager,ShiroFilterFactoryBean三个Bean的注入
ShiroFilterFactoryBean类
setLoginUrl方法--设置用户登录页面
setUnauthorizedUrl方法--设置用户无权限跳转页面
五:编写Controller
@Controller
public class UserController {
@RequestMapping("/{url}")
public String urlGo(@PathVariable("url") String url) {
return url;
}
@RequestMapping("/loginGo")
public String Login(String username,
String password) {
try {
//得到subject
Subject subject = SecurityUtils.getSubject();
//用令牌封装信息
UsernamePasswordToken token = new UsernamePasswordToken(username, password);
subject.login(token);//进入域realm验证username
//向session添加用户信息
subject.getSession().setAttribute("user",subject.getPrincipal());
return "index";
} catch (UnknownAccountException e) {
e.printStackTrace();
return "login";
} catch (IncorrectCredentialsException e) {
e.printStackTrace();
return "login";
}
}
/**
* 当前用户退出
* @return
*/
@RequestMapping("/logout")
public String logout(){
Subject subject = SecurityUtils.getSubject();
subject.logout();
return "login";
}
}
当前操作用户“Subject”
Subject subject = SecurityUtils.getSubject();
用令牌封装信息
UsernamePasswordToken token = new UsernamePasswordToken(username, password);