#Shiro框架学习笔记(一)
#############################################################################
###一、sessionValidationScheduler的使session失效执行流程(SessionManeger)###
#############################################################################
1.ExecutorServiceSessionValidationScheduler
public void run() {
if (log.isDebugEnabled()) {
log.debug("Executing session validation...");
}
long startTime = System.currentTimeMillis();
//(1)调用AbstractValidatingSessionManager.validateSessions()方法
this.sessionManager.validateSessions();
long stopTime = System.currentTimeMillis();
if (log.isDebugEnabled()) {
log.debug("Session validation completed successfully in " + (stopTime - startTime) + " milliseconds.");
}
}
2.AbstractValidatingSessionManager.validateSessions()方法
public void validateSessions() {
if (log.isInfoEnabled()) {
log.info("Validating all active sessions...");
}
int invalidCount = 0;
Collection<Session> activeSessions = this.getActiveSessions();
if (activeSessions != null && !activeSessions.isEmpty()) {
Iterator i$ = activeSessions.iterator();
while(i$.hasNext()) {
Session s = (Session)i$.next();
try {
SessionKey key = new DefaultSessionKey(s.getId());
//(2)调用validate()方法
this.validate(s, key);
} catch (InvalidSessionException var8) {
if (log.isDebugEnabled()) {
boolean expired = var8 instanceof ExpiredSessionException;
String msg = "Invalidated session with id [" + s.getId() + "]" + (expired ? " (expired)" : " (stopped)");
log.debug(msg);
}
++invalidCount;
}
}
}
if (log.isInfoEnabled()) {
String msg = "Finished session validation.";
if (invalidCount > 0) {
msg = msg + " [" + invalidCount + "] sessions were stopped.";
} else {
msg = msg + " No sessions were stopped.";
}
log.info(msg);
}
}
3.AbstractValidatingSessionManager.validate()方法
3.1 AbstractValidatingSessionManager
protected void validate(Session session, SessionKey key) throws InvalidSessionException {
try {
//(3)调用dpValidate()方法,如何session失效抛出InvalidSessionException异常
this.doValidate(session);
} catch (ExpiredSessionException var4) {
this.onExpiration(session, var4, key);
throw var4;
} catch (InvalidSessionException var5) {
//(4)捕获InvalidSessionExceptiony异常,调用onInvalidation()方法
this.onInvalidation(session, var5, key);
throw var5;
}
}
3.2 AbstractValidatingSessionManager
protected void doValidate(Session session) throws InvalidSessionException {
if (session instanceof ValidatingSession) {
//调用ValidatingSession.validate()方法
((ValidatingSession)session).validate();
} else {
String msg = "The " + this.getClass().getName() + " implementation only supports validating " + "Session implementations of the " + ValidatingSession.class.getName() + " interface. " + "Please either implement this interface in your session implementation or override the " + AbstractValidatingSessionManager.class.getName() + ".doValidate(Session) method to perform validation.";
throw new IllegalStateException(msg);
}
}
3.3 SimpleSession
public void validate() throws InvalidSessionException {
if (this.isStopped()) {
String msg = "Session with id [" + this.getId() + "] has been " + "explicitly stopped. No further interaction under this session is " + "allowed.";
throw new StoppedSessionException(msg);
} else if (this.isTimedOut()) {
this.expire();
Date lastAccessTime = this.getLastAccessTime();
long timeout = this.getTimeout();
Serializable sessionId = this.getId();
DateFormat df = DateFormat.getInstance();
String msg = "Session with id [" + sessionId + "] has expired. " + "Last access time: " + df.format(lastAccessTime) + ". Current time: " + df.format(new Date()) + ". Session timeout is set to " + timeout / 1000L + " seconds (" + timeout / 60000L + " minutes)";
if (log.isTraceEnabled()) {
log.trace(msg);
}
//抛出ExpiredSessionException异常(实现了InvalidSessionException)
throw new ExpiredSessionException(msg);
}
}
4.AbstractValidatingSessionManager.onInvalidation()方法
protected void onInvalidation(Session s, InvalidSessionException ise, SessionKey key) {
if (ise instanceof ExpiredSessionException) {
this.onExpiration(s, (ExpiredSessionException)ise, key);
} else {
log.trace("Session with id [{}] is invalid.", s.getId());
try {
//(5)调用onStop()方法
this.onStop(s);
//(6)调用notifyStop()方法
this.notifyStop(s);
} finally {
//(7)最终调用afterStopped()方法
this.afterStopped(s);
}
}
}
##################################################################
###二、Shiro简单实现登录校验与权限验证的流程(SecurityManager)###
##################################################################
ApplicationCode--> Subject --> SecurityManager --> Realm
(The current user) (manages all Subject) (access your sercurity data)
1.LoginController
@RequestMapping(value = "/login",method = RequestMethod.POST)
@ResponseBody
public ResultVo<Map<String,Object>> doLogin(User user, HttpServletRequest request){
Map<String,Object> map=new HashMap<>();
if (StringUtils.isEmpty(user.getUsername())){
return ResultVoUtil.failed("请输入用户名!");
}
if (StringUtils.isEmpty(user.getPassword())){
return ResultVoUtil.failed("请输入密码!");
}
//使用Shiro进行登录校验 SecurityUtils.getSubject().login(token);
try {
//(1)获取认证对象
Subject subject = SecurityUtils.getSubject();
//(2)实例化Token对象
UsernamePasswordToken token=new UsernamePasswordToken(user.getUsername(),user.getPassword());
//(3)进行登录认证
subject.login(token);(进入UserRealm的doGetAuthenticationInfo)
}catch (Exception e){
return ResultVoUtil.failed("账号密码有误!");
}
map.put("url",request.getContextPath()+"/index");
return ResultVoUtil.success(map);
}
2.UserRealm
public class UserRealm extends AuthorizingRealm {
@Autowired
UserService userService;
@Autowired
RoleService roleService;
@Autowired
PermissionService permissionService;
/**
* 授权信息,用于进行权限认证
*/
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
//(1) 获得签名, 可做进一步查询
User user= (User) principalCollection.getPrimaryPrincipal();
//(2)创建SimpleAuthenticationInfo对象
SimpleAuthorizationInfo info=new SimpleAuthorizationInfo();
//(3)查询角色、权限信息
Set<String> roles = roleService.findRolesByUser(user);
info.setRoles(roles);
Set<String> permissions = permissionService.findPermissionsByUser(user);
info.addStringPermissions(permissions);
return info;
}
/**
* 认证信息,主要针对用户登录,
*/
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
//(1)获取登录的token
UsernamePasswordToken token= (UsernamePasswordToken) authenticationToken;
//(2)获取username和password,调用登录
String username=token.getUsername();
String password=new String(token.getPassword());
User user=new User();
user.setUsername(username);
user.setPassword(password);
User login = userService.login(user);
//(3)登录失败
if (null==login){
throw new AccountException("账号或密码不正确!");
}
if (user.getStatus()==0){
throw new DisabledAccountException("帐号已经禁止登录!");
}
//(4)登录成功
user.setUpdatetime(new Date());
userService.updateUser(user);
return new SimpleAuthenticationInfo(user,user.getPassword(),user.getUsername());
}
}
3.配置文件
<!-- (二)SecurityManager -->
<bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">
<property name="realm" ref="userRealm"/>
<property name="sessionManager" ref="sessionManager"/>
<property name="rememberMeManager" ref="rememberMeManager"/>
<property name="cacheManager" ref="customShiroCacheManager"/>
</bean>
<!-- ShiroCacheManager --> <!-- 用于缓存AuthenticationInfo -->
<bean id="customShiroCacheManager" class="com.brillilab.ssmdemo.common.shiro.cache.impl.CustomShiroCacheManager">
<property name="shiroCacheManager" ref="jedisShiroCacheManager"/>
</bean>
<!-- shiro 缓存实现,对ShiroCacheManager,我是采用redis的实现 -->
<bean id="jedisShiroCacheManager" class="com.brillilab.ssmdemo.common.shiro.cache.impl.JedisShiroCacheManager">
<property name="jedisManager" ref="jedisManager"/>
</bean>
<!-- 授权 认证 -->
<bean id="userRealm" class="com.brillilab.ssmdemo.common.shiro.realms.UserRealm" >
<property name="cacheManager" ref="customShiroCacheManager"/>
<property name="cachingEnabled" value="false"/>
<property name="authenticationCachingEnabled" value="true"/>
<property name="authenticationCacheName" value="authenticationCache"/>
<property name="authorizationCachingEnabled" value="true"/>
<property name="authorizationCacheName" value="authorizationCache"/>
</bean>
#############################################################
###三、Shiro简单实现登录拦截和权限拦截(使用自定义拦截器)###
#############################################################
(一)自定义拦截器的配置
<!-- (五)shiro权限过滤器 -->
<bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">
<property name="securityManager" ref="securityManager" />
<property name="loginUrl" value="/login" />
<property name="successUrl" value="/index" />
<property name="unauthorizedUrl" value="/login" />
<!-- 过滤器映射 -->
<property name="filterChainDefinitions" >
<value>
/common/** = anon
/login = anon
/index = anon
/user/insert = login,permission
/user/delete = login,permission
</value>
</property>
<property name="filters">
<util:map>
<entry key="login" value-ref="login"></entry>
<entry key="role" value-ref="role"></entry>
</util:map>
</property>
</bean>
<!-- 自定义拦截器 -->
<bean id="login" class="com.brillilab.ssmdemo.common.shiro.filter.LoginFilter"/>
<bean id="role" class="com.brillilab.ssmdemo.common.shiro.filter.RoleFilter"/>
<bean id="permission" class="com.brillilab.ssmdemo.common.shiro.filter.PermissionFilter"/>
(一)登录拦截
1.LoginFilter
public class LoginFilter extends AccessControlFilter {
/**
* 写如何能通过该拦截器的逻辑
*/
@Override
protected boolean isAccessAllowed(ServletRequest request, ServletResponse response, Object o) throws Exception {
//(1)获取认证信息
User token = (User)SecurityUtils.getSubject().getPrincipal();
//(2)登录请求直接放行
if(null != token || isLoginRequest(request, response)){
return true;
}
//(3)非登录请求,重定向到登录页面
ResultVo result = ResultVoUtil.failed("当前用户没有登录!");
WebUtil.jsonOut(response,result);
return false;
}
/**
* isAccessAllowed返回值为fales时经过该方法
*/
@Override
protected boolean onAccessDenied(ServletRequest request, ServletResponse response) throws Exception {
//保存Request和Response 到登录后的链接
saveRequestAndRedirectToLogin(request, response);
return false;
}
}
(二)权限拦截
2.RoleFilter
public class RoleFilter extends AccessControlFilter {
/**
* 写如何能通过该拦截器的逻辑
*/
@Override
protected boolean isAccessAllowed(ServletRequest request, ServletResponse response, Object value) throws Exception {
//(1)获取认证实体
Subject subject = getSubject(request, response);
//(2)进行角色校验(角色为"1"能通过)
if (subject.hasAllRoles(Arrays.asList("1"))){
return true;
}
//(3)未通过角色校验重定向回登录页面
((HttpServletResponse)response).sendRedirect(request.getServletContext().getContextPath()+"/login");
return false;
}
/**
* isAccessAllowed返回值为fales时经过该方法
*/
@Override
protected boolean onAccessDenied(ServletRequest request, ServletResponse response) throws Exception {
//(3)未通过角色校验重定向回登录页面
//((HttpServletResponse)response).sendRedirect(request.getServletContext().getContextPath()+"/login");
Subject subject = getSubject(request, response);
if (subject.getPrincipal()==null){
//未登录重定向登录页面
saveRequest(request);
WebUtils.issueRedirect(request,response,((HttpServletRequest)request).getContextPath()+"/login");
}else {
//已登录重定向未授权错误页面
WebUtils.issueRedirect(request,response,((HttpServletRequest)request).getContextPath()+"/error/unauthorizerror");
}
return false;
}
}
3.PermissionFilter
public class PermissionFilter extends AccessControlFilter {
/**
* 写如何能通过该拦截器的逻辑
*/
@Override
protected boolean isAccessAllowed(ServletRequest request, ServletResponse response, Object o) throws Exception {
//(1)获取认证实体
Subject subject = getSubject(request,response);
//(2)进行权限校验
//①获取请求url
HttpServletRequest httpRequest=(HttpServletRequest)request;
String url = httpRequest.getRequestURI();
String contextPath = httpRequest.getContextPath();
if (url!=null && url.startsWith(contextPath)){
url = url.replaceFirst(contextPath,"");
}
//②权限校验
if (subject.isPermitted(url)){
return true;
}
return false;
}
/**
* isAccessAllowed返回值为fales时经过该方法
*/
@Override
protected boolean onAccessDenied(ServletRequest request, ServletResponse response) throws Exception {
//(3)未通过权限校验的逻辑
Subject subject = getSubject(request, response);
if (subject.getPrincipal()==null){
//未登录重定向登录页面
saveRequest(request);
WebUtils.issueRedirect(request,response,((HttpServletRequest)request).getContextPath()+"/login");
}else {
//已登录重定向未授权错误页面
WebUtil.jsonOut(response,ResultVoUtil.failed("用户未被授权该操作"));
}
return false;
}
}
#############################################################
###四、Shiro页面内容的授权显示 ###
#############################################################
1.<shiro:guest>标签中的类容在游客访问时显示
<!-- shiro标签测试 -->
<shiro:guest>
<li class="nav-item">
<a class="nav-link" href="/login">Login</a>
</li
</shiro:guest>
2.<shiro:hasRole name="1">标签中的内容在用户登录情况下,角色包含name属性值时显示
<shiro:hasRole name="1">
<li class="nav-item">
<a class="nav-link" href="#">管理员</a>
</li
</shiro:hasRole>
3.<shiro:hasPermission name="/user/insert">标签中的类容在用户登录情况下,权限包含name属性值时显示
<shiro:hasPermission name="/user/insert">
<li class="nav-item">
<a class="nav-link" href="#">能够添加用户</a>
</li
</shiro:hasPermission>
#############################################################################
###一、sessionValidationScheduler的使session失效执行流程(SessionManeger)###
#############################################################################
1.ExecutorServiceSessionValidationScheduler
public void run() {
if (log.isDebugEnabled()) {
log.debug("Executing session validation...");
}
long startTime = System.currentTimeMillis();
//(1)调用AbstractValidatingSessionManager.validateSessions()方法
this.sessionManager.validateSessions();
long stopTime = System.currentTimeMillis();
if (log.isDebugEnabled()) {
log.debug("Session validation completed successfully in " + (stopTime - startTime) + " milliseconds.");
}
}
2.AbstractValidatingSessionManager.validateSessions()方法
public void validateSessions() {
if (log.isInfoEnabled()) {
log.info("Validating all active sessions...");
}
int invalidCount = 0;
Collection<Session> activeSessions = this.getActiveSessions();
if (activeSessions != null && !activeSessions.isEmpty()) {
Iterator i$ = activeSessions.iterator();
while(i$.hasNext()) {
Session s = (Session)i$.next();
try {
SessionKey key = new DefaultSessionKey(s.getId());
//(2)调用validate()方法
this.validate(s, key);
} catch (InvalidSessionException var8) {
if (log.isDebugEnabled()) {
boolean expired = var8 instanceof ExpiredSessionException;
String msg = "Invalidated session with id [" + s.getId() + "]" + (expired ? " (expired)" : " (stopped)");
log.debug(msg);
}
++invalidCount;
}
}
}
if (log.isInfoEnabled()) {
String msg = "Finished session validation.";
if (invalidCount > 0) {
msg = msg + " [" + invalidCount + "] sessions were stopped.";
} else {
msg = msg + " No sessions were stopped.";
}
log.info(msg);
}
}
3.AbstractValidatingSessionManager.validate()方法
3.1 AbstractValidatingSessionManager
protected void validate(Session session, SessionKey key) throws InvalidSessionException {
try {
//(3)调用dpValidate()方法,如何session失效抛出InvalidSessionException异常
this.doValidate(session);
} catch (ExpiredSessionException var4) {
this.onExpiration(session, var4, key);
throw var4;
} catch (InvalidSessionException var5) {
//(4)捕获InvalidSessionExceptiony异常,调用onInvalidation()方法
this.onInvalidation(session, var5, key);
throw var5;
}
}
3.2 AbstractValidatingSessionManager
protected void doValidate(Session session) throws InvalidSessionException {
if (session instanceof ValidatingSession) {
//调用ValidatingSession.validate()方法
((ValidatingSession)session).validate();
} else {
String msg = "The " + this.getClass().getName() + " implementation only supports validating " + "Session implementations of the " + ValidatingSession.class.getName() + " interface. " + "Please either implement this interface in your session implementation or override the " + AbstractValidatingSessionManager.class.getName() + ".doValidate(Session) method to perform validation.";
throw new IllegalStateException(msg);
}
}
3.3 SimpleSession
public void validate() throws InvalidSessionException {
if (this.isStopped()) {
String msg = "Session with id [" + this.getId() + "] has been " + "explicitly stopped. No further interaction under this session is " + "allowed.";
throw new StoppedSessionException(msg);
} else if (this.isTimedOut()) {
this.expire();
Date lastAccessTime = this.getLastAccessTime();
long timeout = this.getTimeout();
Serializable sessionId = this.getId();
DateFormat df = DateFormat.getInstance();
String msg = "Session with id [" + sessionId + "] has expired. " + "Last access time: " + df.format(lastAccessTime) + ". Current time: " + df.format(new Date()) + ". Session timeout is set to " + timeout / 1000L + " seconds (" + timeout / 60000L + " minutes)";
if (log.isTraceEnabled()) {
log.trace(msg);
}
//抛出ExpiredSessionException异常(实现了InvalidSessionException)
throw new ExpiredSessionException(msg);
}
}
4.AbstractValidatingSessionManager.onInvalidation()方法
protected void onInvalidation(Session s, InvalidSessionException ise, SessionKey key) {
if (ise instanceof ExpiredSessionException) {
this.onExpiration(s, (ExpiredSessionException)ise, key);
} else {
log.trace("Session with id [{}] is invalid.", s.getId());
try {
//(5)调用onStop()方法
this.onStop(s);
//(6)调用notifyStop()方法
this.notifyStop(s);
} finally {
//(7)最终调用afterStopped()方法
this.afterStopped(s);
}
}
}
##################################################################
###二、Shiro简单实现登录校验与权限验证的流程(SecurityManager)###
##################################################################
ApplicationCode--> Subject --> SecurityManager --> Realm
(The current user) (manages all Subject) (access your sercurity data)
1.LoginController
@RequestMapping(value = "/login",method = RequestMethod.POST)
@ResponseBody
public ResultVo<Map<String,Object>> doLogin(User user, HttpServletRequest request){
Map<String,Object> map=new HashMap<>();
if (StringUtils.isEmpty(user.getUsername())){
return ResultVoUtil.failed("请输入用户名!");
}
if (StringUtils.isEmpty(user.getPassword())){
return ResultVoUtil.failed("请输入密码!");
}
//使用Shiro进行登录校验 SecurityUtils.getSubject().login(token);
try {
//(1)获取认证对象
Subject subject = SecurityUtils.getSubject();
//(2)实例化Token对象
UsernamePasswordToken token=new UsernamePasswordToken(user.getUsername(),user.getPassword());
//(3)进行登录认证
subject.login(token);(进入UserRealm的doGetAuthenticationInfo)
}catch (Exception e){
return ResultVoUtil.failed("账号密码有误!");
}
map.put("url",request.getContextPath()+"/index");
return ResultVoUtil.success(map);
}
2.UserRealm
public class UserRealm extends AuthorizingRealm {
@Autowired
UserService userService;
@Autowired
RoleService roleService;
@Autowired
PermissionService permissionService;
/**
* 授权信息,用于进行权限认证
*/
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
//(1) 获得签名, 可做进一步查询
User user= (User) principalCollection.getPrimaryPrincipal();
//(2)创建SimpleAuthenticationInfo对象
SimpleAuthorizationInfo info=new SimpleAuthorizationInfo();
//(3)查询角色、权限信息
Set<String> roles = roleService.findRolesByUser(user);
info.setRoles(roles);
Set<String> permissions = permissionService.findPermissionsByUser(user);
info.addStringPermissions(permissions);
return info;
}
/**
* 认证信息,主要针对用户登录,
*/
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
//(1)获取登录的token
UsernamePasswordToken token= (UsernamePasswordToken) authenticationToken;
//(2)获取username和password,调用登录
String username=token.getUsername();
String password=new String(token.getPassword());
User user=new User();
user.setUsername(username);
user.setPassword(password);
User login = userService.login(user);
//(3)登录失败
if (null==login){
throw new AccountException("账号或密码不正确!");
}
if (user.getStatus()==0){
throw new DisabledAccountException("帐号已经禁止登录!");
}
//(4)登录成功
user.setUpdatetime(new Date());
userService.updateUser(user);
return new SimpleAuthenticationInfo(user,user.getPassword(),user.getUsername());
}
}
3.配置文件
<!-- (二)SecurityManager -->
<bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">
<property name="realm" ref="userRealm"/>
<property name="sessionManager" ref="sessionManager"/>
<property name="rememberMeManager" ref="rememberMeManager"/>
<property name="cacheManager" ref="customShiroCacheManager"/>
</bean>
<!-- ShiroCacheManager --> <!-- 用于缓存AuthenticationInfo -->
<bean id="customShiroCacheManager" class="com.brillilab.ssmdemo.common.shiro.cache.impl.CustomShiroCacheManager">
<property name="shiroCacheManager" ref="jedisShiroCacheManager"/>
</bean>
<!-- shiro 缓存实现,对ShiroCacheManager,我是采用redis的实现 -->
<bean id="jedisShiroCacheManager" class="com.brillilab.ssmdemo.common.shiro.cache.impl.JedisShiroCacheManager">
<property name="jedisManager" ref="jedisManager"/>
</bean>
<!-- 授权 认证 -->
<bean id="userRealm" class="com.brillilab.ssmdemo.common.shiro.realms.UserRealm" >
<property name="cacheManager" ref="customShiroCacheManager"/>
<property name="cachingEnabled" value="false"/>
<property name="authenticationCachingEnabled" value="true"/>
<property name="authenticationCacheName" value="authenticationCache"/>
<property name="authorizationCachingEnabled" value="true"/>
<property name="authorizationCacheName" value="authorizationCache"/>
</bean>
#############################################################
###三、Shiro简单实现登录拦截和权限拦截(使用自定义拦截器)###
#############################################################
(一)自定义拦截器的配置
<!-- (五)shiro权限过滤器 -->
<bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">
<property name="securityManager" ref="securityManager" />
<property name="loginUrl" value="/login" />
<property name="successUrl" value="/index" />
<property name="unauthorizedUrl" value="/login" />
<!-- 过滤器映射 -->
<property name="filterChainDefinitions" >
<value>
/common/** = anon
/login = anon
/index = anon
/user/insert = login,permission
/user/delete = login,permission
</value>
</property>
<property name="filters">
<util:map>
<entry key="login" value-ref="login"></entry>
<entry key="role" value-ref="role"></entry>
</util:map>
</property>
</bean>
<!-- 自定义拦截器 -->
<bean id="login" class="com.brillilab.ssmdemo.common.shiro.filter.LoginFilter"/>
<bean id="role" class="com.brillilab.ssmdemo.common.shiro.filter.RoleFilter"/>
<bean id="permission" class="com.brillilab.ssmdemo.common.shiro.filter.PermissionFilter"/>
(一)登录拦截
1.LoginFilter
public class LoginFilter extends AccessControlFilter {
/**
* 写如何能通过该拦截器的逻辑
*/
@Override
protected boolean isAccessAllowed(ServletRequest request, ServletResponse response, Object o) throws Exception {
//(1)获取认证信息
User token = (User)SecurityUtils.getSubject().getPrincipal();
//(2)登录请求直接放行
if(null != token || isLoginRequest(request, response)){
return true;
}
//(3)非登录请求,重定向到登录页面
ResultVo result = ResultVoUtil.failed("当前用户没有登录!");
WebUtil.jsonOut(response,result);
return false;
}
/**
* isAccessAllowed返回值为fales时经过该方法
*/
@Override
protected boolean onAccessDenied(ServletRequest request, ServletResponse response) throws Exception {
//保存Request和Response 到登录后的链接
saveRequestAndRedirectToLogin(request, response);
return false;
}
}
(二)权限拦截
2.RoleFilter
public class RoleFilter extends AccessControlFilter {
/**
* 写如何能通过该拦截器的逻辑
*/
@Override
protected boolean isAccessAllowed(ServletRequest request, ServletResponse response, Object value) throws Exception {
//(1)获取认证实体
Subject subject = getSubject(request, response);
//(2)进行角色校验(角色为"1"能通过)
if (subject.hasAllRoles(Arrays.asList("1"))){
return true;
}
//(3)未通过角色校验重定向回登录页面
((HttpServletResponse)response).sendRedirect(request.getServletContext().getContextPath()+"/login");
return false;
}
/**
* isAccessAllowed返回值为fales时经过该方法
*/
@Override
protected boolean onAccessDenied(ServletRequest request, ServletResponse response) throws Exception {
//(3)未通过角色校验重定向回登录页面
//((HttpServletResponse)response).sendRedirect(request.getServletContext().getContextPath()+"/login");
Subject subject = getSubject(request, response);
if (subject.getPrincipal()==null){
//未登录重定向登录页面
saveRequest(request);
WebUtils.issueRedirect(request,response,((HttpServletRequest)request).getContextPath()+"/login");
}else {
//已登录重定向未授权错误页面
WebUtils.issueRedirect(request,response,((HttpServletRequest)request).getContextPath()+"/error/unauthorizerror");
}
return false;
}
}
3.PermissionFilter
public class PermissionFilter extends AccessControlFilter {
/**
* 写如何能通过该拦截器的逻辑
*/
@Override
protected boolean isAccessAllowed(ServletRequest request, ServletResponse response, Object o) throws Exception {
//(1)获取认证实体
Subject subject = getSubject(request,response);
//(2)进行权限校验
//①获取请求url
HttpServletRequest httpRequest=(HttpServletRequest)request;
String url = httpRequest.getRequestURI();
String contextPath = httpRequest.getContextPath();
if (url!=null && url.startsWith(contextPath)){
url = url.replaceFirst(contextPath,"");
}
//②权限校验
if (subject.isPermitted(url)){
return true;
}
return false;
}
/**
* isAccessAllowed返回值为fales时经过该方法
*/
@Override
protected boolean onAccessDenied(ServletRequest request, ServletResponse response) throws Exception {
//(3)未通过权限校验的逻辑
Subject subject = getSubject(request, response);
if (subject.getPrincipal()==null){
//未登录重定向登录页面
saveRequest(request);
WebUtils.issueRedirect(request,response,((HttpServletRequest)request).getContextPath()+"/login");
}else {
//已登录重定向未授权错误页面
WebUtil.jsonOut(response,ResultVoUtil.failed("用户未被授权该操作"));
}
return false;
}
}
#############################################################
###四、Shiro页面内容的授权显示 ###
#############################################################
1.<shiro:guest>标签中的类容在游客访问时显示
<!-- shiro标签测试 -->
<shiro:guest>
<li class="nav-item">
<a class="nav-link" href="/login">Login</a>
</li
</shiro:guest>
2.<shiro:hasRole name="1">标签中的内容在用户登录情况下,角色包含name属性值时显示
<shiro:hasRole name="1">
<li class="nav-item">
<a class="nav-link" href="#">管理员</a>
</li
</shiro:hasRole>
3.<shiro:hasPermission name="/user/insert">标签中的类容在用户登录情况下,权限包含name属性值时显示
<shiro:hasPermission name="/user/insert">
<li class="nav-item">
<a class="nav-link" href="#">能够添加用户</a>
</li
</shiro:hasPermission>