shiro官方网址:http://shiro.apache.org/
shiro的quickstart项目:https://github.com/apache/shiro/tree/master/samples/quickstart
quickstart项目可以有利于我们快速了解Shiro的使用
①先在setting的plugins下安装好ini插件
②需要在File Types的INI Config下添加一个*.ini,这样就ini就会高亮了
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-QtPex5c5-1597063229989)(C:\Users\76532\AppData\Roaming\Typora\typora-user-images\image-20200809175707144.png)]
在对于quickstart项目的搬运到自己项目的时候,需要注意自己选择的shiro版本
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-BeCb9l8F-1597063230002)(C:\Users\76532\AppData\Roaming\Typora\typora-user-images\image-20200809162749109.png)]
master版本中,在现在导入的shiro-core已经不存在
<dependency>
<groupId>org.apache.shirogroupId>
<artifactId>shiro-coreartifactId>
<version>1.5.3version>
dependency>
import org.apache.shiro.ini.IniSecurityManagerFactory;
现在新版已经在config中了,所以选好版本的quickstart模板,避免出错,而且IniSecurityManagerFactory已经过时了,官方不建议使用
import org.apache.shiro.config.IniSecurityManagerFactory;
通过QuickStart类的代码可以知道一些运用语法
//获取当前对象Subject
Subject currentUser = SecurityUtils.getSubject();
//获取当前对象的Session
Session session = currentUser.getSession();
//生成令牌
UsernamePasswordToken token = new UsernamePasswordToken("lonestarr", "vespa");
//设置记住我
token.setRememberMe(true);
//执行登陆操作
currentUser.login(token);
//是否具有当前具有的角色
currentUser.hasRole("schwartz")
//是否具有当前具有的权限
currentUser.isPermitted("lightsaber:wield")
//注销
currentUser.logout();
//退出
System.exit(0);
Subject:主体;
SecurityManager:相当于SpringMVC中的DispatcherServlet或者Struts2中的FilterDispatcher;它管理着所有Subject、且负责进行认证和授权、及会话、缓存的管理。
Realm:可以有1个或多个Realm,是安全实体数据源;可以是JDBC实现,也可以是LDAP实现,或者内存实现等等;
<dependency>
<groupId>org.apache.shirogroupId>
<artifactId>shiro-springartifactId>
<version>1.5.3version>
dependency>
ShiroConfig
在这个类中,更多的是对于ShiroFilterFactoryBean的编写
①对于一些路由接口权限的配置
②对于逻辑性跳转的编写,如:当没有登陆时,没有权限时等一些情况跳转的页面路由
@Configuration
public class ShiroConfig {
/**
* 创建Realm对象
*/
@Bean
public UserRealm userRealm(){
return new UserRealm();
}
/**
* 创建SecurityManager**
*/
@Bean
public DefaultWebSecurityManager defaultWebSecurityManager(@Qualifier("userRealm") UserRealm userRealm){
DefaultWebSecurityManager defaultWebSecurityManager =new DefaultWebSecurityManager();
defaultWebSecurityManager.setRealm(userRealm);
return defaultWebSecurityManager;
}
/**
* ShiroFilterFactoryBean的创建
*/
@Bean
public ShiroFilterFactoryBean getShiroFilterFactoryBean(@Qualifier("defaultWebSecurityManager") DefaultWebSecurityManager defaultWebSecurityManager ){
ShiroFilterFactoryBean bean = new ShiroFilterFactoryBean();
bean.setSecurityManager(defaultWebSecurityManager);
/*
添加shiro内置过滤器
anon:无需认证就可以访问
authc:必须认证了才能访问
user: 必须用于才能用记住我功能
perms:拥有某个资源权限才能访问
role: 拥有某个角色权限才能访问
*/
Map<String,String> filterMap=new LinkedHashMap<>();
filterMap.put("/add","perms[user:add]");
filterMap.put("/update","perms[user:update]");
bean.setUnauthorizedUrl("/Unauthor");
bean.setFilterChainDefinitionMap(filterMap);
bean.setLoginUrl("/toLogin");
return bean;
}
}
userRealm
该类的功能是
①在访问到一些需要权限的路由时候,它会来先进行授权doGetAuthorizationInfo()方法,再进行访问
②认证是对于登录的账号密码进行一个认证,看是否存在该账号,账号密码是否正确
public class UserRealm extends AuthorizingRealm {
@Autowired
private UserService userService;
/**
* 授权
* @param principalCollection
* @return
*/
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
SimpleAuthorizationInfo Info = new SimpleAuthorizationInfo();
Subject subject = SecurityUtils.getSubject();
User user = (User) subject.getPrincipal();
Info.addStringPermission(user.getPerms());
return Info;
}
/**
* 认证
* @param authenticationToken
* @return
* @throws AuthenticationException
*/
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
UsernamePasswordToken userToken = (UsernamePasswordToken) authenticationToken;
User user = userService.findUserByName(userToken.getUsername());
if (user ==null){
return null;
}
return new SimpleAuthenticationInfo(user,user.getPassword(),"");
}
}
登录
我觉得和userRealm的交互更多在于subject的使用,通过SecurityUtils获取到当前的对象的一些属性进行操作。
@RequestMapping("/login")
public String login(String username,String password,Model model){
//获取用户
Subject subject = SecurityUtils.getSubject();
//将用户数据封装到token
UsernamePasswordToken Token = new UsernamePasswordToken(username,password);
try {
subject.login(Token);
} catch (UnknownAccountException e) {
model.addAttribute("msg","用户名不存在");
return "login";
}catch (IncorrectCredentialsException e){
model.addAttribute("msg","账号密码错误");
return "login";
}
return "index";
}
对druid和mybatis所需所有依赖进行导入,再配置属性,最后编写mapper和dao,配置好mybatis的对应mapper和pojo位置,在测试类测试,再进行整合使用到UserRealm中
导入依赖
<dependency>
<groupId>com.github.theborakompanionigroupId>
<artifactId>thymeleaf-extras-shiroartifactId>
<version>2.0.0version>
dependency>
配置ShiroDialect
/**
* ShiroDialect整合thymeleaf和shiro
*/
@Bean
public ShiroDialect getShiroDialect(){
return new ShiroDialect();
}
html
只有配置了xmlns:shiro="http://www.pollix.at/thymeleaf/shiro"才会自动提示shiro:的相关语法
<html lang="en" xmlns:th="http://www.thymeleaf.org" xmlns:shiro="http://www.pollix.at/thymeleaf/shiro">
① shiro:guest是验证是否有经过认证,经过认证就会隐藏登录
② shiro:hasPermission="‘user:add’"是有该授权就会显示
<a th:href="@{/toLogin}" shiro:guest="true">登录a>
<div shiro:hasPermission="'user:add'"><a th:href="@{/add}">添加a>div>
<div shiro:hasPermission="'user:update'"><a th:href="@{/update}">更新a>div>