一. 权限管理
1.1 权限获取
之前我们一直在模拟数据库中的数据
现在我们直接去数据库获取真实权限数据
public class FilterChainDefinitionMapFactory {
@Autowired
private IPermissionService permissionService;
public Map< String, String> creatMap ( ) {
Map< String, String> map = new LinkedHashMap < > ( ) ;
map. put ( "/login" , "anon" ) ;
map. put ( "*.js" , "anon" ) ;
map. put ( "*.css" , "anon" ) ;
map. put ( "/login/**" , "anon" ) ;
map. put ( "/css/**" , "anon" ) ;
map. put ( "/js/**" , "anon" ) ;
map. put ( "/easyui/**" , "anon" ) ;
map. put ( "/images/**" , "anon" ) ;
List< Permission> perms = permissionService. findAll ( ) ;
perms. forEach ( p- > {
map. put ( p. getUrl ( ) , "aisellPerms[" + p. getSn ( ) + "]" ) ;
} ) ;
map. put ( "/**" , "authc" ) ;
return map;
}
}
1.2 当前用户权限
1. PermissionRepositroy 这里添加一个方法
自己写JPQL获取
public interface PermissionRepositroy extends BaseRepository < Permission, Long> {
@Query ( "select p.sn from Employee e join e.roles r join r.permissions p where e.id=?1" )
Set< String> findSnByUser ( Long userId) ;
}
2. 业务层 IPermissionService 添加获取当前用户权限方法
public interface IPermissionService extends IBaseService < Permission, Long> {
Set< String> findSnByUser ( ) ;
}
3. PermissionServiceImpl 实现
@Service
public class PermissionServiceImpl extends BaseServiceImpl < Permission, Long> implements IPermissionService {
@Autowired
private PermissionRepositroy permissionRepositroy;
@Override
public Set< String> findSnByUser ( ) {
Employee loginUser = UserContext. getUser ( ) ;
return permissionRepositroy. findSnByUser ( loginUser. getId ( ) ) ;
}
}
4. AisellRealm 获取权限
public class AisellRealm extends AuthorizingRealm {
@Autowired
private IEmployeeService employeeService;
@Autowired
private IPermissionService permissionService;
protected AuthorizationInfo doGetAuthorizationInfo ( PrincipalCollection principalCollection) {
SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo ( ) ;
Set< String> perms = permissionService. findSnByUser ( ) ;
authorizationInfo. setStringPermissions ( perms) ;
return authorizationInfo;
}
. . . . .
}
二. ajax 请求权限拦截
2.1 自定义权限,写一个类
我们在删除一条数据的时候,因为用的是ajax请求,
所以在删除失败时,错误提示是undefined
我们需要显示正确的错误提示信息
解决方案:
自定义一个类,继承 PermissionsAuthorizationFilter
重写 onAccessDenied
细节:
ajax的请求头有一个: X-Requested-With:XMLHttpRequest
只需要判断请求头有没有这个参数
协议转换成Http协议
public class AiSellPermissionsAuthorizationFilter extends PermissionsAuthorizationFilter {
protected boolean onAccessDenied ( ServletRequest request, ServletResponse response) throws IOException {
Subject subject = this . getSubject ( request, response) ;
if ( subject. getPrincipal ( ) == null) {
this . saveRequestAndRedirectToLogin ( request, response) ;
} else {
HttpServletRequest req = ( HttpServletRequest) request;
HttpServletResponse resp = ( HttpServletResponse) response;
resp. setContentType ( "application/json;charset=UTF-8" ) ;
String xhr = req. getHeader ( "X-Requested-With" ) ;
if ( "XMLHttpRequest" . equals ( xhr) ) {
resp. getWriter ( ) . print ( "{\"success\":false,\"msg\":\"你没有权限\"}" ) ;
} else {
String unauthorizedUrl = this . getUnauthorizedUrl ( ) ;
if ( StringUtils. hasText ( unauthorizedUrl) ) {
WebUtils. issueRedirect ( request, response, unauthorizedUrl) ;
} else {
WebUtils. toHttp ( response) . sendError ( 401 ) ;
}
}
}
return false ;
}
}
2.2 权限配置 applicationContext-shiro.xml中配置
< bean id= "shiroFilter" class = "org.apache.shiro.spring.web.ShiroFilterFactoryBean" >
. . . . . .
< property name= "filters" >
< map>
< ! -- aisellPerms 知道找这个过滤器 -- >
< entry key= "aisellPerms" value- ref= "aisellFilter" / >
< / map>
< / property>
< / bean>
! -- 配置自己的过滤器 -- >
< bean id= "aisellFilter" class = "com.yangrui.aisell.web.shiro.AiSellPermissionsAuthorizationFilter" / >
2.3 权限使用
记得要加上aisellPerms,这样才知道找我们自己的权限过滤器
public class FilterChainDefinitionMapFactory {
@Autowired
private IPermissionService permissionService;
. . . . . .
List< Permission> perms = permissionService. findAll ( ) ;
perms. forEach ( p- > {
map. put ( p. getUrl ( ) , "aisellPerms[" + p. getSn ( ) + "]" ) ;
} ) ;
map. put ( "/**" , "authc" ) ;
return map;
}
三. shiro标签
3.1 引入标签
< % @ taglib prefix= "shiro" uri= "http://shiro.apache.org/tags" % >
3.2 拿到主体的标签
< shiro: principal property= "username" / >
3.3 权限判断的标签
有employee:delete权限才显示删除按钮
< shiro: hasPermission name= "employee:delete" >
< a href= "javascript:;" data- method= "delete" class = "easyui-linkbutton" data- options= "iconCls:'icon-remove',plain:true" > 删除< / a>
< / shiro: hasPermission>
四. 菜单管理(不带权限)
菜单基本结构显示
4.1 Menu对象
@Entity
@Table ( name = "menu" )
public class Menu extends BaseDomain {
private String name;
private String url;
private String icon;
@OneToMany
@JoinColumn ( name = "parent_id" )
private List< Menu> children = new ArrayList < > ( ) ;
. . .
}
4.2 获取父级菜单
获取所有父级菜单
父级菜单没有url,根据这个入手
public interface MenuRepositroy extends BaseRepository < Menu, Long> {
@Query ( "select m from Menu m where m.url is null" )
List< Menu> findParentMenus ( ) ;
}
4.3 IMenuService
public interface IMenuService extends IBaseService < Menu, Long> {
List< Menu> findParentMenus ( ) ;
}
4.4 MenuServiceImpl
@Service
public class MenuServiceImpl extends BaseServiceImpl < Menu, Long> implements IMenuService {
@Override
public List< Menu> findParentMenus ( ) {
return menuRepository. findParentMenus ( ) ;
}
}
4.5 MenuController
@RequestMapping ( "/findParentMenus" )
@ResponseBody
public List< Menu> findParentMenus ( ) {
return menuService. findParentMenus ( ) ;
4.6 主页面main访问
$( "#menuid" ) . tree ( {
method: 'post' ,
url: '/menu/findParentMenus' ,
. . .
}
五. 菜单管理(带权限显示)
每个用户登录后是根据自己的权限查找到相应的菜单
5.1 Menu对象
Entity
@Table ( name = "menu" )
public class Menu extends BaseDomain {
private String name;
private String url;
private String icon;
@Transient
private List< Menu> children = new ArrayList < > ( ) ;
@ManyToOne
@JoinColumn ( name = "parent_id" )
@JsonIgnore
private Menu parent;
. . .
get set方法
}
5.2 Permission对象
@Entity
@Table ( name = "permission" )
public class Permission extends BaseDomain {
private String name;
private String url;
private String descs;
private String sn;
@ManyToOne
@JoinColumn ( name = "menu_id" )
private Menu menu;
. . .
get set方法
}
5.3 Role对象
@Entity
@Table ( name = "role" )
public class Role extends BaseDomain {
private String name;
private String sn;
@ManyToMany
@JoinTable ( name = "role_permission" , joinColumns = @JoinColumn ( name = "role_id" ) ,
inverseJoinColumns = @JoinColumn ( name = "permission_id" ) )
private List< Permission> permissions = new ArrayList < > ( ) ;
. . .
get set方法
}
5.4 MenuRepositroy 增加用户菜单方法
public interface MenuRepositroy extends BaseRepository < Menu, Long> {
@Query ( "select distinct m from Employee e join e.roles r join r.permissions p join p.menu m where e.id=?1" )
List< Menu> findMenusByUser ( Long userId) ;
@Query ( "select m from Menu m where m.url is null" )
List< Menu> findParentMenus ( ) ;
}
5.5 MenuServiceImpl
List集合装起来
@Service
public class MenuServiceImpl extends BaseServiceImpl < Menu, Long> implements IMenuService {
@Autowired
private MenuRepositroy menuRepositroy;
@Override
public List< Menu> findParentMenus ( ) {
List< Menu> parentMenus = new ArrayList < > ( ) ;
Employee loginUser = UserContext. getUser ( ) ;
List< Menu> menus = menuRepositroy. findMenusByUser ( loginUser. getId ( ) ) ;
menus. forEach ( m- > {
Menu parentMenu = m. getParent ( ) ;
if ( ! parentMenus. contains ( parentMenu) ) {
parentMenus. add ( parentMenu) ;
}
parentMenu. getChildren ( ) . add ( m) ;
} ) ;
return parentMenus;
}
}