springboot 与shiro整合——(一)页面过滤器实现拦截
springboot 与shiro整合——(二)mybatis用户登录认证
一 导读和实现效果
实现逻辑
ShiroConfig (设置 filterMap.put("/addMenu1","perms[menu:add]"))——》单击href链接——》UserRealm (先调用认证获取Principal,然后调用doGetAuthorizationInfo中info授权信息)——》有权限: 执行Conroller(addMenu1) ——》没权限:执行Conroller(noAuth)
未授权效果如下:
授权后如下:
1.noAuth.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>未授权提示页面</title>
</head>
<body>
亲,你未经授权访问该页面
</body>
</html>
2.在shiroConfig配置授权权限限定和未授权页面
filterMap.put("/addUser","perms[user:add]");
filterMap.put("/addMenu1","perms[menu:add]");
shiroFilterFactoryBean.setUnauthorizedUrl("/noAuth");
详细代码如下:
@Configuration
public class ShiroConfig {
/*
创建ShiroFilterFactoryBean
*/
@Bean
public ShiroFilterFactoryBean getShiroFilterFactoryBean(@Qualifier("securityManager")DefaultWebSecurityManager securityManager)
{
ShiroFilterFactoryBean shiroFilterFactoryBean=new ShiroFilterFactoryBean();
//1.设置安全管理器
shiroFilterFactoryBean.setSecurityManager(securityManager);
/**2. 添加shiro内置过滤器,可以实现权限相关的拦截
* 常用的过滤器:
* anon:无需认证(登录)可以访问
* authc: 必须认证才能访问
* user: 如果使用rememberMe的功能可以直接访问
* perms:该资源必须得到资源权限才可以访问
* role:该资源必须得到角色权限才能访问
**/
Map<String,String> filterMap=new LinkedHashMap<String,String>();
filterMap.put("/sysmenu/*","anon");
filterMap.put("/index","anon");
filterMap.put("/login","anon");
filterMap.put("/noAuth","anon");
//授权过滤器
//注意:当前授权拦截后,shiro会跳转到未授权页面
filterMap.put("/addUser","perms[user:add]");
filterMap.put("/addMenu1","perms[menu:add]");
filterMap.put("/*","authc");
//修改跳转的登录页面
shiroFilterFactoryBean.setLoginUrl("/tologin");
//设置未授权提示页面
shiroFilterFactoryBean.setUnauthorizedUrl("/noAuth");
shiroFilterFactoryBean.setFilterChainDefinitionMap(filterMap);
return shiroFilterFactoryBean;
}
/*
创建DefaultWebSecurityManager
*/
@Bean(name="securityManager")
public DefaultWebSecurityManager getDefaultWebSecurityManager(@Qualifier("userRealm")UserRealm userRealm)
{
DefaultWebSecurityManager securityManager=new DefaultWebSecurityManager();
securityManager.setRealm(userRealm);
return securityManager;
}
/*
创建Realm
*/
@Bean(name="userRealm")
public UserRealm getReal(){
return new UserRealm();
}
}
3.在UserReaml类里doGetAuthenticationInfo函数返回值加上SimpleAuthenticationInfo(user,user.getPassword(),"");
在doGetAuthorizationInfo函数里的info添加授权info.addStringPermissions
package com.lulu.configuration;
import com.lulu.bean.Menu;
import com.lulu.bean.Role;
import com.lulu.bean.User;
import com.lulu.service.MenuService;
import com.lulu.service.RoleService;
import com.lulu.service.UserService;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.subject.Subject;
import org.springframework.beans.factory.annotation.Autowired;
import javax.security.sasl.AuthenticationException;
import java.util.ArrayList;
import java.util.List;
public class UserRealm extends AuthorizingRealm {
@Autowired
private UserService userService;
@Autowired
private MenuService menuService;
@Autowired
private RoleService roleService;
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
System.out.println("执行授权逻辑");
System.out.println("执行授权逻辑");
SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
//添加资源的授权字符串
// info.addStringPermission("menu:add");
//到数据库查询当前登录用户的授权字符串
//获取当前登录用户
Subject subject = SecurityUtils.getSubject();
User user = (User) subject.getPrincipal();
System.out.println(user.getId());
System.out.println(user.getUsername());
List<Menu> menuList = menuService.getMenusByHrId(user.getId());
List<Role> roleList = roleService.findRolesByUserName(user.getUsername());
System.out.println("权限有" + menuList.size());
List<String> listrole = new ArrayList<>();
List<String> listmenu = new ArrayList<>();
if (roleList.size() != 0) {
for (Role role : roleList) {
if (!listrole.contains(role.getRolename())) {
listrole.add(role.getRolename());
System.out.println(role.getRolename());
}
}
}
if (menuList.size() != 0) {
for (Menu menu : menuList) {
if (!listmenu.contains(menu.getPermission())) {
listmenu.add(menu.getPermission());
System.out.println(menu.getPermission());
}
}
}
info.addRoles(listrole);
info.addStringPermissions(listmenu);
return info;
}
@Override
protected org.apache.shiro.authc.AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken arg0) {
System.out.println("执行认证逻辑");
//编写shiro判读逻辑,判断用户名和密码
UsernamePasswordToken token=(UsernamePasswordToken)arg0;
System.out.println("token.getUsername()====="+token.getUsername());
User user=userService.getUserByNum(token.getUsername());
if(user==null)
{
return null;
}
return new SimpleAuthenticationInfo(user,user.getPassword(),"");
}
}
4.在html页面添加链接
<li><a href="/addMenu1">菜单1</a></li>
5.Controller
@RequestMapping("/noAuth")
public String noAuth()
{
return "noAuth";
}
@RequestMapping("/addMenu1")
public String addMenu1()
{
return "menu/addMenu";
}
6.addMenu.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>新增菜单</title>
</head>
<body>
<h3>新增菜单</h3>
</body>
</html>