环境搭建
1.引入依赖
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-spring</artifactId>
<version>1.4.0</version>
</dependency>
2.编写配置类 自定义Realm
shiro需要我们提供doGetAuthenticationInfo和doGetAuthorizationInfo的实现,已完成登录认证和权限信息。
自定义Realm,继承与AuthorizingRealm
public class MyRealm extends AuthorizingRealm {
//授权
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
return null;
}
//认证
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
return null;
}
}
3.ShiroConfig shiro配置
@Configuration
public class ShiroConfig {
//当前用户 第三步
@Bean
public ShiroFilterFactoryBean getShiroFilterFactoryBean(@Qualifier("securityManager") DefaultWebSecurityManager defaultWebSecurityManager){
ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
shiroFilterFactoryBean.setSecurityManager(defaultWebSecurityManager);
return shiroFilterFactoryBean;
}
//安全管理器 第二步
@Bean(name="securityManager")
public DefaultWebSecurityManager getSecurityManager(@Qualifier("userRealm") MyRealm myRealm){
DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
securityManager.setRealm(myRealm);
return securityManager;
}
//获取安全数据 第一步
@Bean(name="userRealm")
public MyRealm getRealm(){
return new MyRealm();
}
}
实现登录拦截
常用的过滤器如下:
authc:所有已登陆用户可访问
roles:有指定角色的用户可访问,通过[ ]指定具体角色,这里的角色名称与数据库中配置一致
perms:有指定权限的用户可访问,通过[ ]指定具体权限,这里的权限名称与数据库中配置一致
anon:所有用户可访问,通常作为指定页面的静态资源时使用
//认证失败、未认证 设置登录请求
shiroFilterFactoryBean.setLoginUrl("/login");
//跳转未授权页面
shiroFilterFactoryBean.setUnauthorizedUrl("/unauthc");
shiroFilterFactoryBean.setSuccessUrl("/home/index");
Map<String,String> filterMap=new LinkedHashMap<>();
filterMap.put("/*", "anon");
filterMap.put("/authc/index", "authc");
filterMap.put("/authc/admin", "roles[admin]");
filterMap.put("/authc/renewable", "perms[Create,Update]");
filterMap.put("/authc/removable", "perms[Delete]");
shiroFilterFactoryBean.setFilterChainDefinitionMap(filterMap);
实现用户认证
//认证
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
System.out.println("执行认证=============");
//从数据库查到用户
UsernamePasswordToken token = (UsernamePasswordToken) authenticationToken;//类型转换
User user = userService.getUserByName(token.getUsername());
if(user==null){
return null;//会自动抛出异常
}
//shiro帮我们做密码认证
return new SimpleAuthenticationInfo(user,user.getPwd(),"");
}
//登录Controller
@RequestMapping("/login")
public String login(String username, String password, Model model){
//获取当前用户
Subject sub = SecurityUtils.getSubject();
//封装用户的登录数据
UsernamePasswordToken token =new UsernamePasswordToken(username,password);
//登录
try {
sub.login(token);//执行登录方法
return "index";
}catch (UnknownAccountException e){//用户名不存在
model.addAttribute("msg","用户名不存在");
return "login";
}catch (IncorrectCredentialsException e){//密码不正确
model.addAttribute("msg","密码不正确");
return "login";
}
}
##实现权限拦截
###配置类ShiroConfig ==>方法
```java
getShiroFilterFactoryBean(@Qualifier("securityManager") DefaultWebSecurityManager defaultWebSecurityManager)
filterMap.put("/user/add","perms[user:add]");
filterMap.put("/user/update","perms[user:update]");
shiroFilterFactoryBean.setUnauthorizedUrl("/unAuth");//未授权 跳转显示未授权
授权
//授权
类 MyRealm==>方法doGetAuthorizationInfo
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
System.out.println("执行授权=============");
SimpleAuthorizationInfo info =new SimpleAuthorizationInfo();
Subject sub = SecurityUtils.getSubject();
User currentUser = (User) sub.getPrincipal();
info.addStringPermission(currentUser.getPerms());
return info;
}
页面权限控制展示—整合Thymeleaf
1.依赖
<dependency>
<groupId>com.github.theborakompanioni</groupId>
<artifactId>thymeleaf-extras-shiro</artifactId>
<version>2.0.0</version>
</dependency>
2.在ShiroConfig中配置ShiroDialect
/**
* shiro方言 支持shiro标签
* @return
*/
@Bean
public ShiroDialect shiroDialect() {
return new ShiroDialect();
}
3.命名空间
<html lang="zh_CN" xmlns:th="http://www.thymeleaf.org"
xmlns:shiro="http://www.pollix.at/thymeleaf/shiro">
//作为属性控制
<button type="button" shiro:authenticated="true" class="btn btn-outline btn-default">
<i class="glyphicon glyphicon-plus" aria-hidden="true"></i>
</button>
//作为标签
<shiro:hasRole name="admin">
<button type="button" class="btn btn-outline btn-default">
<i class="glyphicon glyphicon-heart" aria-hidden="true"></i>
</button>
</shiro:hasRole>
4.标签说明
guest标签
shiro:guest
</shiro:guest>
用户没有身份验证时显示相应信息,即游客访问信息。
user标签
shiro:user
</shiro:user>
用户已经身份验证/记住我登录后显示相应的信息。
authenticated标签
shiro:authenticated
</shiro:authenticated>
用户已经身份验证通过,即Subject.login登录成功,不是记住我登录的。
notAuthenticated标签
shiro:notAuthenticated
</shiro:notAuthenticated>
用户已经身份验证通过,即没有调用Subject.login进行登录,包括记住我自动登录的也属于未进行身份验证。
principal标签
<shiro: principal/>
<shiro:principal property=“username”/>
相当于((User)Subject.getPrincipals()).getUsername()。
lacksPermission标签
<shiro:lacksPermission name=“org:create”>
</shiro:lacksPermission>
如果当前Subject没有权限将显示body体内容。
hasRole标签
<shiro:hasRole name=“admin”>
</shiro:hasRole>
如果当前Subject有角色将显示body体内容。
hasAnyRoles标签
<shiro:hasAnyRoles name=“admin,user”>
</shiro:hasAnyRoles>
如果当前Subject有任意一个角色(或的关系)将显示body体内容。
lacksRole标签
<shiro:lacksRole name=“abc”>
</shiro:lacksRole>
如果当前Subject没有角色将显示body体内容。
hasPermission标签
<shiro:hasPermission name=“user:create”>
</shiro:hasPermission>
如果当前Subject有权限将显示body体内容
验证当前用户是否拥有指定权限
添加
具体实现可参考如下文章
https://blog.youkuaiyun.com/u012796085/article/details/79900936