一、shiro授权角色、权限
1.Mapper层
①.SysUserMapper
package com.zking.ssm.book.mapper;
import com.zking.ssm.book.model.SysUser;
import org.apache.ibatis.annotations.Param;
import org.springframework.stereotype.Repository;
import java.util.Set;
@Repository
public interface SysUserMapper {
/**
* 根据用户账号查询用户对象信息
*
* @param username
* @return
*/
SysUser userLogin(@Param("username") String username);
/**
* 根据username查询该用户的所有角色,用于角色验证
*/
Set<String> findRoles(@Param("username") String username);
/**
* 根据username查询他所拥有的权限信息,用于权限判断
*/
Set<String> findPermissions(@Param("username") String username);
}
②.SysUserMapper.xml
<select id="findRoles" resultType="java.lang.String">
select
r.rolename
from
t_sys_user u,t_sys_user_role ur,t_sys_role r
where
u.userid=ur.userid and ur.roleid=r.roleid
and u.username=#{username}
</select>
<select id="findPermissions" resultType="java.lang.String">
select
p.permission
from
t_sys_user u,t_sys_user_role ur,t_sys_role r,
t_sys_role_permission rp,t_sys_permission p
where
u.userid=ur.userid and ur.roleid=r.roleid and
r.roleid=rp.roleid and rp.perid=p.perid and
u.username=#{username}
</select>
2.Service层
①.ISysUserService
package com.zking.ssm.book.service;
import com.zking.ssm.book.model.SysUser;
import org.apache.ibatis.annotations.Param;
import org.springframework.stereotype.Repository;
import java.util.Set;
public interface ISysUserService {
/**
* 根据用户账号查询用户对象信息
*
* @param username
* @return
*/
SysUser userLogin(String username);
/**
* 根据username查询该用户的所有角色,用于角色验证
*/
Set<String> findRoles(String username);
/**
* 根据username查询他所拥有的权限信息,用于权限判断
*/
Set<String> findPermissions(String username);
}
②.SysUserServiceImpl
package com.zking.ssm.book.service.impl;
import com.zking.ssm.book.mapper.SysUserMapper;
import com.zking.ssm.book.model.SysUser;
import com.zking.ssm.book.service.ISysUserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.Set;
@Service
public class SysUserServiceImpl implements ISysUserService {
@Autowired
private SysUserMapper sysUserMapper;
@Override
public SysUser userLogin(String username) {
return sysUserMapper.userLogin(username);
}
@Override
public Set<String> findRoles(String username) {
return sysUserMapper.findRoles(username);
}
@Override
public Set<String> findPermissions(String username) {
return sysUserMapper.findPermissions(username);
}
}
3.重写自定义Realm配置Shiro授权认证
package com.zking.ssm.book.shiro;
import com.zking.ssm.book.model.SysUser;
import com.zking.ssm.book.service.ISysUserService;
import org.apache.shiro.authc.*;
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.util.ByteSource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.util.Set;
/**
* 自定义Realm的安全数据源,采用数据库方式
* spring-shiro.xml
* <bean id="" class="ShiroRealm">
*/
public class ShiroRealm extends AuthorizingRealm {
@Autowired
private ISysUserService sysUserService;
/**
* 授权
* @param principalCollection
* @return
*/
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
//获取登录账号
String username = principalCollection.getPrimaryPrincipal().toString();
//根据username获取用户对应角色
Set<String> roles = sysUserService.findRoles(username);
//根据username获取用户对应角色权限
Set<String> permissions = sysUserService.findPermissions(username);
//创建SimpleAuthorizationInfo
SimpleAuthorizationInfo simple=new SimpleAuthorizationInfo();
//填充用户的角色和权限
simple.setRoles(roles);
simple.setStringPermissions(permissions);
return simple;
}
/**
* 认证
* @param authenticationToken 传入的账号密码令牌Token
* @return
* @throws AuthenticationException
*/
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
//获取账号
String username = authenticationToken.getPrincipal().toString();
//获取密码
String password = authenticationToken.getCredentials().toString();
//根据账号查询数据库中的用户对象信息
SysUser sysUser = sysUserService.userLogin(username);
//判断sysUser是否为空
if(null==sysUser)
throw new UnknownAccountException("账号不存在!");
//创建SimpleAuthenticationInfo,传入正确的账号和密码(来自于数据库)
SimpleAuthenticationInfo simple1=new SimpleAuthenticationInfo(
sysUser.getUsername(),
sysUser.getPassword(),
ByteSource.Util.bytes(sysUser.getSalt()),
this.getName()
);
return simple1;
}
}
4.spring-shiro.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<!--1.注册自定义的Realm,采用数据库方式-->
<bean id="shiroRealm" class="com.zking.ssm.book.shiro.ShiroRealm">
<!--开启缓存-->
<property name="cachingEnabled" value="true"/>
<!--开启授权缓存-->
<property name="authorizationCachingEnabled" value="true"/>
<!--设置ehcache的中的缓存对象名-->
<property name="authorizationCacheName" value="shiroAuthzCache"/>
<!--配置Shiro明文密码如何进行加密-->
<!--注意:重要的事情说三次~~~~~~此处加密方式要与用户注册时的算法一致 -->
<!--注意:重要的事情说三次~~~~~~此处加密方式要与用户注册时的算法一致 -->
<!--注意:重要的事情说三次~~~~~~此处加密方式要与用户注册时的算法一致 -->
<!--以下三个配置告诉shiro将如何对用户传来的明文密码进行加密-->
<property name="credentialsMatcher">
<bean id="credentialsMatcher" class="org.apache.shiro.authc.credential.HashedCredentialsMatcher">
<!--指定hash算法为MD5-->
<property name="hashAlgorithmName" value="md5"/>
<!--指定散列次数为1024次-->
<property name="hashIterations" value="1024"/>
<!--true指定Hash散列值使用Hex加密存. false表明hash散列值用用Base64-encoded存储-->
<property name="storedCredentialsHexEncoded" value="true"/>
</bean>
</property>
</bean>
<!--2.创建安全管理器SecurityManage,并更换Realm-->
<bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">
<property name="realm" ref="shiroRealm" />
<!--配置会话管理器-->
<property name="sessionManager" ref="sessionManager"/>
<!--配置缓存管理器-->
<property name="cacheManager" ref="cacheManager"/>
</bean>
<!--3.配置Shiro核心过滤器-->
<!--Shiro核心过滤器-->
<bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">
<!-- Shiro的核心安全接口,这个属性是必须的 -->
<property name="securityManager" ref="securityManager" />
<!-- 身份验证失败,跳转到登录页面 -->
<property name="loginUrl" value="/home/index.html"/>
<!-- 身份验证成功,跳转到指定页面 -->
<!--<property name="successUrl" value="/index.jsp"/>-->
<!-- 权限验证失败,跳转到指定页面 -->
<!--<property name="unauthorizedUrl" value="/noauthorizeUrl.jsp"/>-->
<!-- Shiro连接约束配置,即过滤链的定义 -->
<property name="filterChainDefinitions">
<value>
<!--anon 表示匿名访问,不需要认证以及授权-->
<!--authc表示需要认证 没有进行身份认证是不能进行访问的-->
/user/userLogin=anon
/book/**=authc
<!-- /css/** = anon
/images/** = anon
/js/** = anon
/ = anon
/user/logout = logout
/user/** = anon
/userInfo/** = authc
/dict/** = authc
/console/** = roles[admin]
/** = anon-->
</value>
</property>
</bean>
<!--4.配置Shiro的生命周期-->
<bean id="lifecycleBeanPostProcessor" class="org.apache.shiro.spring.LifecycleBeanPostProcessor"/>
shiro好处:安全性高
shiro坏处:性能差
二、注解式开发
1.常用注解介绍
@RequiresAuthenthentication:表示当前Subject已经通过login进行身份验证;即 Subjecj.isAuthenticated()返回 true
@RequiresUser:表示当前Subject已经身份验证或者通过记住我登录的
@RequiresGuest:表示当前Subject没有身份验证或者通过记住我登录过,即是游客身份
@RequiresRoles(value = {"admin","user"},logical = Logical.AND):表示当前Subject需要角色admin和user
@RequiresPermissions(value = {"user:delete","user:b"},logical = Logical.OR):表示当前Subject需要权限user:delete或者user:b注:
必须将Shiro注解的开启放置到spring-mvc.xml中(即放在springMVC容器中加载),不然Shiro注解开启无效!!!
2.注解的使用
①.BookController
/**
* 返回List<T>格式的JSON数据
* @param book
* @param req
* @return
*/
@RequiresRoles(value = {"管理员","高级用户"},logical = Logical.OR)
@RequestMapping("/queryLstBook")
@ResponseBody
public List<Book> queryLstBook(Book book,HttpServletRequest req){
PageBean pageBean=new PageBean();
pageBean.setRequest(req);
List<Book> books = bookService.queryBookPager(book,pageBean);
return books;
}
/**
* 查询返回JSON数据的混合格式
* 例如:
* {'total':81,'rows':[{},{},{},...]}
* @param book
* @param req
* @return
*/
@RequiresPermissions("bookmanager:book:update")
@RequestMapping("/queryLstBook1")
@ResponseBody
public Map<String,Object> queryLstBook1(Book book,HttpServletRequest req){
PageBean pageBean=new PageBean();
pageBean.setRequest(req);
List<Book> books = bookService.queryBookPager(book,pageBean);
Map<String,Object> json=new HashMap<>();
json.put("total",pageBean.getTotal());
json.put("rows",books);
return json;
}
②.Spring-mvc.xml
<!--配置Shiro注解式权限-->
<bean class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator"
depends-on="lifecycleBeanPostProcessor">
<property name="proxyTargetClass" value="true"></property>
</bean>
<bean class="org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor">
<property name="securityManager" ref="securityManager"/>
</bean>
最后执行结果为:
至此,shiro授权-SSM介绍完毕,由于作者水平有限难免有疏漏,欢迎留言纠错。