Shiro是一个强大易用的java安全,提供了认证、授权、加密、会话管理、与web集成、缓存等功能,对于任何一个应用程序,都可以提供全面的安全服务,相比其他安全框架,shiro要简单的多。
既可以用在controller中,也可以用在service中建议将shiro注解放入controller,因为如果service层使用了spring的事物注解,那么shiro注解将无效
1、 简单的身份验证,支持多种数据源
2、对角色的简单授权,支持细粒度的授权(方法)
3、支持一级缓存,以提升应用程序的性能
4、内置基于POJO的企业会话管理,适用于web及非web环境
5、非常简单的API加密
6、不跟任何框架绑定,可以独立运行
Subject.login(token)
进行登录,其会自动委托给 Security Manager
,调用之前必须通过 SecurityUtils.setSecurityManager()
设置;SecurityManager
负责真正的身份验证逻辑;它会委托给 Authenticator
进行身份验证;Authenticator
才是真正的身份验证者,Shiro API
中核心的身份认证入口点,此处可以自定义插入自己的实现;Authenticator
可能会委托给相应的 AuthenticationStrategy
进行多 Realm 身份验证,默认 ModularRealmAuthenticator
会调用 AuthenticationStrategy
进行多 Realm 身份验证;Authenticator
会把相应的 token
传入 Realm
,从 Realm
获取身份验证信息,如果没有返回 则抛出异常表示身份验证失败了。此处可以配置多个 Realm
,将按照相应的顺序及策略进行访问。首先要导入标签库;
<%@ taglib uri="http://shiro.apache.org/tags" prefix="shiro" %>:导入标签库;
:游客访问;
:用户需要登录或记住我;
:用户需要登录;
:用户需要拥有某种角色访问;
:用户需要拥有某些角色;
:用户需要拥有某资源;进行显示
导入
<html
xmlns:shiro="http://www.pollix.at/thymeleaf/shiro"
>
html>
shiro:guest:游客访问;
shiro:user:用户需要登录或记住我;
shiro:authenticated:用户需要登录;
shiro:hasRole:用户需要某角色;
shiro:hasAnyRoles:用户需要某些角色;
shiro:hasPermission:用户需要某权限;
-----------------------------------------------------------
<li shiro:hasAnyRoles="admin,manager">:用户需要 admin 或 manager 角色可访问;
<li><span shiro:principal/>li>:身份验证器包装的用户名时,页面获取用户名;
<span shiro:principal property="loginName"/>:身份验证器中包装 user 对象时,页面获取用户名;
<input type="hidden" id="userId" th:value="${session.user.userId}">:页面获取 session 中 user 对象;
可以在maven仓库包https://mvnrepository.com/,根据三要素进行查找
<properties>
<shiro.version>1.7.1shiro.version>
properties>
<dependency>
<groupId>org.apache.shirogroupId>
<artifactId>shiro-coreartifactId>
<version>${shiro.version}version>
dependency>
<dependency>
<groupId>org.apache.shirogroupId>
<artifactId>shiro-springartifactId>
<version>${shiro.version}version>
dependency>
<dependency>
<groupId>org.apache.shirogroupId>
<artifactId>shiro-webartifactId>
<version>${shiro.version}version>
dependency>
<dependency>
<groupId>org.apache.shirogroupId>
<artifactId>shiro-aspectjartifactId>
<version>${shiro.version}version>
dependency>
<dependency>
<groupId>org.apache.shirogroupId>
<artifactId>shiro-ehcacheartifactId>
<version>${shiro.version}version>
dependency>
项目跑起来了,只是控制台输出了
SLF4J: Failed to load class "org.slf4j.impl.StaticLoggerBinder".
SLF4J: Defaulting to no-operation (NOP) logger implementation
SLF4J: See http://www.slf4j.org/codes.html#StaticLoggerBinder for further details.
需要配置日志包
shiro使用slf4j作为日志框架,所以必需配置slf4j。同时,使用log4j作为底层的日志实现框架。
org.slf4j
slf4j-api
1.7.25
org.slf4j
slf4j-log4j12
1.7.25
log4j
log4j
1.2.17
在Spring框架中集成Shiro,本质上是与Spring IoC容器和Spring MVC框架集成.
<filter>
<filter-name>shiroFilterfilter-name>
<filter-class>org.springframework.web.filter.DelegatingFilterProxyfilter-class>
<init-param>
<param-name>targetFilterLifecycleparam-name>
<param-value>trueparam-value>
init-param>
filter>
<filter-mapping>
<filter-name>shiroFilterfilter-name>
<url-pattern>/*url-pattern>
filter-mapping>
其中包含过滤设置。此文件名为spring-shiro.xml,里面定义了需要的Bean,完成诸多功能。
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-4.3.xsd
">
<context:component-scan base-package="com.qq"/>
<bean id="userRealm" class="com.qq.realm.UserRealm"/>
<bean id="advisorAutoProxyCreator" class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator" depends-on="lifecycleBeanPostProcessor">
<property name="proxyTargetClass" value="true"/>
bean>
<bean id="lifecycleBeanPostProcessor" class="org.apache.shiro.spring.LifecycleBeanPostProcessor" />
<bean class="org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor">
<property name="securityManager" ref="securityManager"/>
bean>
<bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">
<property name="realm" ref="userRealm"/>
bean>
<bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">
<property name="securityManager" ref="securityManager"/>
<property name="loginUrl" value="/login/view"/>
<property name="unauthorizedUrl" value="/login/view" />
<property name="successUrl" value="/home"/>
<property name="filterChainDefinitions" >
<value>
/login/view = anon
/back/student/zzz =authc,roles[admin]
/back/** = authc
value>
property>
beans>
或者:springShiro.xml
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-4.0.xsd"
default-lazy-init="true">
<bean id="myRealm" class="com.sfac.springMvc.config.MyRealm" />
<bean id="rememberMeCookie" class="org.apache.shiro.web.servlet.SimpleCookie">
<property name="name" value="rememberMe"/>
<property name="maxAge" value="604800"/>
<property name="httpOnly" value="true"/>
bean>
<bean id="rememberMeManager" class="org.apache.shiro.web.mgt.CookieRememberMeManager">
<property name="cookie" ref="rememberMeCookie"/>
bean>
<bean id="sessionManager" class="org.apache.shiro.web.session.mgt.DefaultWebSessionManager">
<property name="globalSessionTimeout" value="6000000"/>
<property name="deleteInvalidSessions" value="true"/>
<property name="sessionIdUrlRewritingEnabled" value="false" />
bean>
<bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">
<property name="realm" ref="myRealm"/>
<property name="rememberMeManager" ref="rememberMeManager">property>
<property name="sessionManager" ref="sessionManager" />
bean>
<bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">
<property name="securityManager" ref="securityManager"/>
<property name="loginUrl" value="/login"/>
<property name="successUrl" value="/common/dashboard"/>
<property name="filterChainDefinitions">
<value>
/static/**=anon
/register=anon
/login=anon
/forgot=anon
/logout=logout
/api/**=anon
/**=authc
value>
property>
bean>
<bean id="lifecycleBeanPostProcessor" class="org.apache.shiro.spring.LifecycleBeanPostProcessor"/>
<bean class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator"
depends-on="lifecycleBeanPostProcessor">
<property name="proxyTargetClass" value="true" />
bean>
<bean class="org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor">
<property name="securityManager" ref="securityManager" />
bean>
beans>
必须是在MVC配置文件中用
将spring-shiro.xml载入。
例子:
身份验证
UserRealm
package com.qq.realm;
import com.qq.model.User;
import com.qq.service.UserService;
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.springframework.beans.factory.annotation.Autowired;
/**
* @description:com.qq.realm_studyssm
* @author: 霏宇
* @time: 2022/8/5,9:55
*/
public class UserRealm extends AuthorizingRealm {
@Autowired
UserService userService;
//授权:
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
String name =(String)principalCollection.getPrimaryPrincipal();
if (name.equals("admin")){
info.addStringPermission("admin");
}else if (name.equals("lisi")){
info.addStringPermission("worker");
info.addRole("admin");
}
return info;
}
/**
* 认证
* @param token
* @return
* @throws AuthenticationException
*/
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
//一旦此用户不存在就主动抛出异常
UsernamePasswordToken upToken = (UsernamePasswordToken)token;
String name =upToken.getUsername();
String password=new String(upToken.getPassword());
User user =userService.selectByName(name);
if(null==user){
throw new UnknownAccountException("你输入的账户不存在!");
}else {
User user2 =userService.selectByNamePassword(name,password);
if(null==user2){
throw new IncorrectCredentialsException("密码错误");
}else {
return new SimpleAuthenticationInfo(token.getPrincipal(),token.getCredentials(),this.getName());
}
}
// if(!name.equals("list")&&!name.equals("admin")){
// throw new UnknownAccountException("你输入的账户不存在!");
// }else {
// //这里假设系统的用户只有两个 (zhangsan,123456)、(lisi,888999)
// if(name.equals("list")&&password.equals("789") ||name.equals("admin")&&password.equals("123456")){
//
// return new SimpleAuthenticationInfo(token.getPrincipal(),token.getCredentials(),this.getName());
//
// }else {
// throw new IncorrectCredentialsException("用户不存在");
// }
//
// }
}
}
或者:MyRealm.java
public class MyRealm extends AuthorizingRealm {
@Autowired
private UserService userService;
@Autowired
private RoleService roleService;
@Autowired
private ResourceService resourceService;
/**
* -资源授权器
*/
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
// 授权类
SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo();
User user = (User) principals.getPrimaryPrincipal();
if (user == null) {
return null;
}
List<Role> roles = Optional
.ofNullable(roleService.getRolesByUserId(user.getId()))
.orElse(Collections.emptyList());
roles.stream().forEach(role -> {
authorizationInfo.addRole(role.getRoleName());
List<Resource> resources = Optional
.ofNullable(resourceService.getResourcesByRoleId(role.getId()))
.orElse(Collections.emptyList());
resources.stream().forEach(resource -> {
authorizationInfo.addStringPermission(resource.getPermission());
});
});
return authorizationInfo;
}
/**
* -身份验证器
*/
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
String userName = (String) token.getPrincipal();
User user = userService.getUserByUserName(userName);
if (user == null) {
throw new UnknownAccountException("The account do not exist.");
}
// realmName: 当前 realm 对象的唯一名字. 调用父类的 getName() 方法
return new SimpleAuthenticationInfo(user, user.getPassword(), getName());
}
}
LoginController
package com.qq.controller;
import com.qq.model.User;
import com.qq.service.UserService;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.IncorrectCredentialsException;
import org.apache.shiro.authc.UnknownAccountException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.subject.Subject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import javax.servlet.http.HttpSession;
/**
* @description:com.qq.controller_studyssm
* @author: 霏宇
* @time: 2022/8/4,14:02
*/
@Controller
@RequestMapping("/login")
public class LoginController {
@Autowired
UserService userService;
@RequestMapping("/view")
String index(){
return "login/view";
}
@RequestMapping("/enter")
String enter(String name, String password, HttpSession session, Model model){
Subject subject = SecurityUtils.getSubject(); //
UsernamePasswordToken token = new UsernamePasswordToken(name, password); //对(用户名、密码)登录方式,用UsernamePasswordToken封装即可
try {
subject.login(token); //调用login()方法。 有可能遭遇两种异常,代表登陆失败。
User user =userService.selectByNamePassword(name,password);
session.setAttribute("USER",user);
} catch (UnknownAccountException e) {
e.printStackTrace();
model.addAttribute("message", "用户名错误!");
return "redirect:view";
} catch (IncorrectCredentialsException e) {
e.printStackTrace();
model.addAttribute("message", "密码错误");
return "redirect:view";
}
System.out.println(subject.isAuthenticated()); //打印下看看是否已认证成功
return "redirect:/back/hui/index";
// User user = userService.selectByNamePassword(name, password);
// if(user==null){
//
// return "redirect:index";
// }else {
// session.setAttribute("USER", user);
// return "redirect:/back/book/index";
// }
}
@RequestMapping("/logout")
String logout(HttpSession session){
session.removeAttribute("USER");
Subject subject =SecurityUtils.getSubject();
subject.logout();
// session.invalidate();
return "redirect:view";
}
}
或者在
UserService
public Result<User> login(User user);
UserServiceImpl
```java
@Service
public class UserServiceImpl implements UserService{
@Override
public ResultEntity login(User user) {
Subject subject = SecurityUtils.getSubject();
UsernamePasswordToken token = new UsernamePasswordToken(user.getUserName(),
MD5Util.getMD5(user.getPassword()));
token.setRememberMe(user.getRememberMe());
return new Result(Result.ResultStatus.SUCCESS.code, "Success", user);
try {
subject.login(token);
subject.checkRoles();
} catch (Exception e) {
e.printStackTrace();
return new Result(Result.ResultStatus.FAILD.code, e.getMessage());
}
Session session = subject.getSession();
session.setAttribute("user", subject.getPrincipal());
}
@GetMapping("/logout")
public String logout() {
Subject subject = SecurityUtils.getSubject();
subject.logout();
return "redirect:/login";
}
}
```
<dependency>
<groupId>org.apache.shirogroupId>
<artifactId>shiro-coreartifactId>
<version>1.4.0version>
dependency>
<dependency>
<groupId>org.apache.shirogroupId>
<artifactId>shiro-springartifactId>
<version>1.4.0version>
dependency>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-thymeleafartifactId>
dependency>
<dependency>
<groupId>com.github.theborakompanionigroupId>
<artifactId>thymeleaf-extras-shiroartifactId>
<version>2.0.0version>
dependency>
#for shiro
#开启Shiro配置,默认为true
shiro.web.enabled=true
#server.servlet.context-path=/shiro
#spring.application.name=shiro
package com.feiyu.sprtingboot.config.shiro;
import com.feiyu.sprtingboot.modules.account.entity.Resource;
import com.feiyu.sprtingboot.modules.account.entity.Role;
import com.feiyu.sprtingboot.modules.account.entity.User;
import com.feiyu.sprtingboot.modules.account.service.ResourceService;
import com.feiyu.sprtingboot.modules.account.service.RoleService;
import com.feiyu.sprtingboot.modules.account.service.UserService;
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.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.util.List;
/**
* @description:com.feiyu.sprtingboot.config.shiro_sprtingboot
* @author: 霏宇
* @time: 2022/8/31,9:41
*/
@Component
public class MyRealm extends AuthorizingRealm {
@Autowired
private UserService userService;
@Autowired
private RoleService roleService;
@Autowired
private ResourceService resourceService;
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
SimpleAuthorizationInfo authorization = new SimpleAuthorizationInfo();
// 从认证中获取当前的信息
User user = (User) principals.getPrimaryPrincipal();
// 从数据库查询当前用户的角色列表,并装载到资源授权器里
List<Role> roles = roleService.getRolesByUserId(user.getId());
roles.stream().forEach(item -> {
authorization.addRole(item.getRoleName());
// authorization.addStringPermission(item.getRoleName());
// 再去查询每个角色拥有的资源列表,并装载到资源授权器里
List<Resource> resources = resourceService.getResourcesByRoleId(item.getId());
resources.stream().forEach(it -> {
authorization.addStringPermission(it.getPermission());
System.out.println(it.getPermission());
});
});
return authorization;
}
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token)
throws AuthenticationException {
// 获取用户名
String userName = (String) token.getPrincipal();
// 通过用户名查找数据库的 user 信息
User user = userService.getUserByUserName(userName);
if (user == null) {
throw new UnknownAccountException("User name is not exit.");
}
// 封装身份验证器
return new SimpleAuthenticationInfo(user, user.getPassword(), getName());
}
}
package com.feiyu.sprtingboot.config.shiro;
import at.pollux.thymeleaf.shiro.dialect.ShiroDialect;
import org.apache.shiro.mgt.SecurityManager;
import org.apache.shiro.spring.LifecycleBeanPostProcessor;
import org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.DependsOn;
import java.util.LinkedHashMap;
import java.util.Map;
/**
* @description:com.feiyu.sprtingboot.config.shiro_sprtingboot
* @author: 霏宇
* @time: 2022/8/31,10:21
*/
@Configuration
public class ShiroConfig {
@Autowired
private MyRealm myRealm;
@Bean
public SecurityManager securityManager() {
DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
securityManager.setRealm(myRealm);
return securityManager;
}
/**
* anon:匿名访问,无需登录 ---- AnonymousFilter
* authc:登录后才能访问 ---- FormAuthenticationFilter
* user:登录过能访问 ---- UserFilter
* logout:登出 ---- LogoutFilter
*/
@Bean
public ShiroFilterFactoryBean shiroFilterFactoryBean() {
ShiroFilterFactoryBean filterFactory = new ShiroFilterFactoryBean();
// 注入安全管理器
filterFactory.setSecurityManager(securityManager());
// 设置登录页面、登录成功页面
filterFactory.setLoginUrl("/login");
filterFactory.setSuccessUrl("/test/thymeleafTest");
// 设置其余地址的访问策略
Map<String, String> filterMap = new LinkedHashMap<>();
// 匿名策略
// 登录注册
filterMap.put("/login", "anon");
filterMap.put("/register", "anon");
// 静态资源
filterMap.put("/favicon.ico", "anon");
filterMap.put("/css/**", "anon");
filterMap.put("/images/**", "anon");
filterMap.put("/js/**", "anon");
filterMap.put("/vendors/**", "anon");
filterMap.put("/static/**", "anon");
// 测试模块
filterMap.put("/test/**", "anon");
// api
filterMap.put("/api/**", "anon");
// 非匿名策略
filterMap.put("/**", "authc");
filterFactory.setFilterChainDefinitionMap(filterMap);
return filterFactory;
}
/**
* - 注册shiro方言,让 thymeleaf 支持 shiro 标签
*/
@Bean
public ShiroDialect shiroDialect(){
return new ShiroDialect();
}
@Bean(name="lifecycleBeanPostProcessor")
public static LifecycleBeanPostProcessor getLifecycleBeanPostProcessor() {
return new LifecycleBeanPostProcessor();
}
/**
* DefaultAdvisorAutoProxyCreator, Advisor 代理类生成器
*/
@Bean
@DependsOn({"lifecycleBeanPostProcessor"})
public DefaultAdvisorAutoProxyCreator advisorAutoProxyCreator(){
DefaultAdvisorAutoProxyCreator advisorAutoProxyCreator = new DefaultAdvisorAutoProxyCreator();
advisorAutoProxyCreator.setProxyTargetClass(true);
return advisorAutoProxyCreator;
}
/**
* - 创建 AuthorizationAttributeSourceAdvisor,扫描 Shiro 注解
*/
@Bean
public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(){
AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor = new AuthorizationAttributeSourceAdvisor();
authorizationAttributeSourceAdvisor.setSecurityManager(securityManager());
return authorizationAttributeSourceAdvisor;
}
}
如果需要加入rememberMeCookie
/**
* -- Remember Me Cookie
*/
@Bean
public SimpleCookie rememberMeCookie() {
//这个参数是 cookie 的名称
SimpleCookie simpleCookie = new SimpleCookie("rememberMe");
//如果 httyOnly 设置为 true,则客户端不会暴露给客户端脚本代码,
//使用 HttpOnly cookie 有助于减少某些类型的跨站点脚本攻击;
simpleCookie.setHttpOnly(true);
//记住我 cookie 生效时间,单位是秒
simpleCookie.setMaxAge(1 * 24 * 60 * 60);
return simpleCookie;
}
/**
* -- 管理器
*/
@Bean
public CookieRememberMeManager rememberMeManager() {
CookieRememberMeManager cookieRememberMeManager = new CookieRememberMeManager();
cookieRememberMeManager.setCookie(rememberMeCookie());
byte[] cipherKey = Base64.decode("wGiHplamyXlVB11UXWol8g==");
cookieRememberMeManager.setCipherService(new AesCipherService());
cookieRememberMeManager.setCipherKey(cipherKey);
return cookieRememberMeManager;
}
/**
* sessionCookie
*/
@Bean
public SimpleCookie sessionCookie() {
SimpleCookie simpleCookie = new SimpleCookie("shiro.sesssion");
simpleCookie.setPath("/");
simpleCookie.setHttpOnly(true);
simpleCookie.setMaxAge(1 * 24 * 60 * 60);
return simpleCookie;
}
在DefaultWebSessionManager 加入
/**
* DefaultAdvisorAutoProxyCreator, Advisor 代理类生成器
Shiro 默认 Cookie 名称是 JSESSIONID,与 Tomcat 等默认JSESSIONID 冲突,我们需要为
Shiro 指定一个不同名称的 Session id,否则抛出 UnknownSessionException: There is no session with id 异常
*/
@Bean
@DependsOn({"lifecycleBeanPostProcessor"})
public DefaultAdvisorAutoProxyCreator advisorAutoProxyCreator(){
DefaultAdvisorAutoProxyCreator advisorAutoProxyCreator = new DefaultAdvisorAutoProxyCreator();
sessionManager.setSessionIdCookie(sessionCookie());
advisorAutoProxyCreator.setProxyTargetClass(true);
// 相隔多久检查一次 session 的有效性
// sessionManager.setSessionValidationInterval(1 * 24 * 60 * 60 * 1000);
// session 有效时间
// sessionManager.setGlobalSessionTimeout(1 * 24 * 60 * 60 * 1000);
return advisorAutoProxyCreator;
}
在SecurityManager 加入
@Bean
public SecurityManager securityManager() {
DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
securityManager.setRealm(myRealm);
securityManager.setRememberMeManager(rememberMeManager());
securityManager.setSessionManager(sessionManager());
return securityManager;
}
UserServiceImpl
@Override
public Result<User> login(User user) {
// 得到 subject
Subject subject = SecurityUtils.getSubject();
// 封装一个登录令牌(装载用户名和密码)
UsernamePasswordToken token = new UsernamePasswordToken(
user.getUserName(),
MD5Util.encode(user.getPassword()));
try {
// subject.login()
subject.login(token);
subject.checkRoles();
// 获取当前用户,并将之设置到 session 中
User temp = (User) subject.getPrincipal();
Session session = subject.getSession();
session.setAttribute("user", temp);
return new Result<User>(Result.ResultStatus.SUCCESS.code, "Success", temp);
} catch (Exception e) {
e.printStackTrace();
LOGGER.debug(e.getMessage());
return new Result<User>(Result.ResultStatus.FAILD.code, e.getMessage());
}
}
/**
* 127.0.0.1/account/users---- get
*/
@RequiresRoles(value = {"admin","manager"},logical = Logical.OR)
@GetMapping(value = "/account/users")
public String userPage(ModelMap modelMap) {
modelMap.addAttribute("template",
"account/users");
return "index";
}
@RequiresPermissions("/api/user/{id}")
public Result<Object> deleteUserById(@PathVariable int id){
return userService.deleteUserById(id);
}
Html页面
<ul class="nav child_menu">
<li shiro:hasAnyRoles="admin,manager,staff"><a href="javascript:void(0);">Profilea>li>
<li shiro:hasAnyRoles="admin,manager"><a href="/account/users">Usersa>li>
<li shiro:hasAnyRoles="admin,manager"><a href="/account/roles">Rolesa>li>
<li shiro:hasAnyRoles="admin,manager"><a href="/account/resources">Resourcesa>li>
ul>
<ul class="nav child_menu">
<shiro:hasPermission name="/test/thymeleafTest">
<li shiro:hasAnyRoles="admin,manager,staff">
<a href="/test/thymeleafTest">ThymeleafTesta>li>
shiro:hasPermission>
<shiro:hasPermission name="/test/vueTest">://用户需要拥有某资源;进行显示
<li shiro:hasAnyRoles="admin,manager,staff"><a href="/test/vueTest">VueTesta>li>
shiro:hasPermission>
<li shiro:hasAnyRoles="admin,manager,staff">
<a>二级菜单<span class="fa fa-chevron-down">span>a>
<ul class="nav child_menu">
<li class="sub_menu"><a href="javascript:void(0);">三级菜单一a>li>
<li><a href="javascript:void(0);">三级菜单二a>li>
ul>
li>
ul>
部分转载于http://www.sfac.xyz:8000/notes/Java/Apache_Shiro.html