导入Shiro依赖库
<dependency>
<groupId>org.apache.shirogroupId>
<artifactId>shiro‐coreartifactId>
<version>1.4.1version>
dependency>
<dependency>
<groupId>org.apache.shirogroupId>
<artifactId>shiro‐webartifactId>
<version>1.4.1version>
dependency>
<dependency>
<groupId>org.apache.shirogroupId>
<artifactId>shiro‐springartifactId>
<version>1.4.1version>
dependency>
本博文配置以1.4.1版本为参考,其他版本如有出入请以官方配置为主
官方配置地址在此博文底部
<web‐app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema‐instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee
http://xmlns.jcp.org/xml/ns/javaee/web‐app_3_1.xsd"
version="3.1">
<context‐param>
<param‐name>contextConfigLocationparam‐name>
<param‐value>classpath:spring‐*.xmlparam‐value>
context‐param>
<listener>
<listener‐class>org.springframework.web.context.ContextLoaderListenerlistener‐class>
listener>
<servlet>
<servlet‐name>springMVCservlet‐name>
<servlet‐class>org.springframework.web.servlet.DispatcherServletservlet‐
class>
<init‐param>
<param‐name>contextConfigLocationparam‐name>
<param‐value>classpath:spring‐context*.xmlparam‐value>
init‐param>
servlet>
<servlet‐mapping>
<servlet‐name>springMVCservlet‐name>
<url‐pattern>*.dourl‐pattern>
servlet‐mapping>
<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>
web‐app>
创建spring-context-shiro.xml
配置shiro
<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">
<!‐‐shiro过滤器‐‐>
<bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">
<property name="securityManager" ref="securityManager">property>
<property name="loginUrl" value="/login.jsp">property>
<!‐‐配置登录成功之后跳转的页面路径此配置一般不使用一般在LoginController中处理逻辑‐‐>
<property name="successUrl" value="/index.jsp">property>
<property name="unauthorizedUrl" value="/">property>
<property name="filterChainDefinitions">
<value>/**=anonvalue>
property>
bean>
<bean id="lifecycleBeanPostProcessor" class="org.apache.shiro.spring.LifecycleBeanPostProcessor">bean>
<!‐‐证书匹配器‐‐>
<bean id="credentialsMatcher"
class="org.apache.shiro.authc.credential.Md5CredentialsMatcher">bean>
<!‐‐使用自带的Realm‐‐>
<bean id="jdbcRealm" class="org.apache.shiro.realm.jdbc.JdbcRealm">
<property name="credentialsMatcher" ref="credentialsMatcher">property>
<property name="permissionsLookupEnabled" value="true">property>
<property name="dataSource" ref="dataSource">property>
bean>
<!‐‐缓存管理‐‐>
<bean id="cacheManager" class="org.apache.shiro.cache.MemoryConstrainedCacheManager">bean>
<!‐‐shiro安全管理器‐‐>
<bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">
<property name="realm" ref="jdbcRealm">property>
<property name="cacheManager" ref="cacheManager">property>
bean>
beans>
如果用注解则需要配置权限验证使用注解
<!‐‐配置权限验证使用注解‐‐>
<aop:config proxy‐target‐class="true">aop:config>
<bean class="org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor">
<property name="securityManager" ref="securityManager">property>
bean>
java配置方式
@Configuration
public class ShiroConfig {
@Bean
public ShiroDialect getShiroDialect(){
return new ShiroDialect();
}
//自定义Realm
@Bean
public MyRealm getMyRealm(){
MyRealm myRealm = new MyRealm();
return myRealm;
}
@Bean
public DefaultWebSecurityManager getDefaultWebSecurityManager(MyRealm myRealm){
DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
//securityManager要完成校验,需要realm
securityManager.setRealm(myRealm);
return securityManager;
}
@Bean
public ShiroFilterFactoryBean shiroFilter(DefaultWebSecurityManager securityManager){
ShiroFilterFactoryBean filter = new ShiroFilterFactoryBean();
//过滤器就是shiro就行权限校验的核心,进行认证和授权是需要SecurityManager的
filter.setSecurityManager(securityManager);
//设置登录网址
filter.setLoginUrl("/user/login");
//设置shiro的拦截规则
// anon 匿名用户可访问
// authc 认证用户可访问
// user 使用RemeberMe的用户可访问
// perms 对应权限可访问
// role 对应的角色可访问
Map<String,String> filterMap = new HashMap<>();
filterMap.put("/","anon");
filterMap.put("/login.html","anon");
filterMap.put("/regist.html","anon");
filterMap.put("/user/login","anon");
filterMap.put("/user/regist","anon");
filterMap.put("/static/**","anon");
filterMap.put("/**","authc");
filter.setFilterChainDefinitionMap(filterMap);
filter.setLoginUrl("/login.html");
//设置未授权访问的页面路径
filter.setUnauthorizedUrl("/login.html");
return filter;
}
}
/**
* 1.创建一个类继承AuthorizingRealm类(实现了Realm接口的类)
* 2.重写doGetAuthorizationInfo和doGetAuthenticationInfo方法
* 3.重写getName方法返回当前realm的一个自定义名称
*/
public class MyRealm extends AuthorizingRealm {
@Resource
private UserDAO userDAO;
@Resource
private RoleDAO roleDAO;
@Resource
private PermissionDAO permissionDAO;
public String getName() {
return "myRealm";
}
/**
* 获取授权数据(将当前用户的角色及权限信息查询出来)
*/
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
//获取用户的用户名
String username = (String) principalCollection.iterator().next();
//根据用户名查询当前用户的角色列表
Set<String> roleNames = roleDAO.queryRoleNamesByUsername(username);
//根据用户名查询当前用户的权限列表
Set<String> ps = permissionDAO.queryPermissionsByUsername(username);
SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
info.setRoles(roleNames);
info.setStringPermissions(ps);
return info;
}
/**
* 获取认证的安全数据(从数据库查询的用户的正确数据)
*/
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
//参数authenticationToken就是传递的 subject.login(token)
// 从token中获取用户名
UsernamePasswordToken token = (UsernamePasswordToken) authenticationToken;
String username = token.getUsername();
//根据用户名,从数据库查询当前用户的安全数据
User user = userDAO.queryUserByUsername(username);
AuthenticationInfo info = new SimpleAuthenticationInfo(
username, //当前用户用户名
user.getUserPwd(), //从数据库查询出来的安全密码
getName());
return info;
}
}
@Configuration
public class ShiroConfig {
//...
@Bean
public HashedCredentialsMatcher getHashedCredentialsMatcher(){
HashedCredentialsMatcher matcher = new HashedCredentialsMatcher();
//matcher就是用来指定加密规则(可自定义加密规则)
matcher.setHashAlgorithmName("md5");
//hash次数
matcher.setHashIterations(1); //此处的循环次数要与用户注册是密码加密次数一致
return matcher;
}
//自定义Realm
@Bean
public MyRealm getMyRealm( HashedCredentialsMatcher matcher ){
MyRealm myRealm = new MyRealm();
myRealm.setCredentialsMatcher(matcher);
return myRealm;
}
//...
}
导入依赖
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-cacheartifactId>
dependency>
<dependency>
<groupId>net.sf.ehcachegroupId>
<artifactId>ehcacheartifactId>
dependency>
<dependency>
<groupId>org.apache.shirogroupId>
<artifactId>shiro-ehcacheartifactId>
<version>1.4.0version>
dependency>
<ehcache updateCheck="false" dynamicConfig="false">
<diskStore path="C:\TEMP" />
<cache name="users" timeToLiveSeconds="300" maxEntriesLocalHeap="1000"/>
<defaultCache name="defaultCache"
maxElementsInMemory="10000"
eternal="false"
timeToIdleSeconds="120"
timeToLiveSeconds="120"
overflowToDisk="false"
maxElementsOnDisk="100000"
diskPersistent="false"
diskExpiryThreadIntervalSeconds="120"
memoryStoreEvictionPolicy="LRU"/>
ehcache>
加入缓存管理(java配置)
@Bean
public EhCacheManager getEhCacheManager(){
EhCacheManager ehCacheManager = new EhCacheManager();
ehCacheManager.setCacheManagerConfigFile("classpath:ehcache.xml");
return ehCacheManager;
}
@Bean
public DefaultWebSecurityManager getDefaultWebSecurityManager(MyRealm myRealm){
DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
securityManager.setRealm(myRealm);
securityManager.setCacheManager(getEhCacheManager());
return securityManager;
}
@Bean
public DefaultWebSessionManager getDefaultWebSessionManager(){
DefaultWebSessionManager sessionManager = new DefaultWebSessionManager();
System.out.println("----------"+sessionManager.getGlobalSessionTimeout()); // 1800000
//配置sessionManager
sessionManager.setGlobalSessionTimeout(5*60*1000);
return sessionManager;
}
@Bean
public DefaultWebSecurityManager getDefaultWebSecurityManager(MyRealm myRealm){
DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
securityManager.setRealm(myRealm);
securityManager.setCacheManager(getEhCacheManager());
securityManager.setSessionManager(getDefaultWebSessionManager());
return securityManager;
}
在过滤器中设置“记住我”可访问的url
// anon 表示未认证可访问的url
// user 表示记住我可访问的url(已认证也可以访问)
//authc 表示已认证可访问的url
//perms 表示必须具备指定的权限才可访问
//logout 表示指定退出的url
filterMap.put("/","anon");
filterMap.put("/index.html","user");
filterMap.put("/login.html","anon");
filterMap.put("/regist.html","anon");
filterMap.put("/user/login","anon");
filterMap.put("/user/regist","anon");
filterMap.put("/layui/**","anon");
filterMap.put("/**","authc");
filterMap.put("/c_add.html","perms[sys:c:save]");
filterMap.put("/exit","logout");
在ShiroConfig.java中配置基于cookie的rememberMe管理器
@Bean
public CookieRememberMeManager cookieRememberMeManager(){
CookieRememberMeManager rememberMeManager = new CookieRememberMeManager();
//cookie必须设置name
SimpleCookie cookie = new SimpleCookie("rememberMe");
cookie.setMaxAge(30*24*60*60);
rememberMeManager.setCookie(cookie);
return rememberMeManager;
}
@Bean
public DefaultWebSecurityManager getDefaultWebSecurityManager(MyRealm myRealm){
DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
securityManager.setRealm(myRealm);
securityManager.setCacheManager(getEhCacheManager());
securityManager.setSessionManager(getDefaultWebSessionManager());
//设置remember管理器
securityManager.setRememberMeManager(cookieRememberMeManager());
return securityManager;
}
登录认证时设置token“记住我”
<form action="/user/login" method="post">
<p>帐号:<input type="text" name="userName"/>p>
<p>密码:<input type="text" name="userPwd"/>p>
<p>记住我:<input type="checkbox" name="rememberMe"/>p>
<p><input type="submit" value="登录"/>p>
form>
控制器
@Controller
@RequestMapping("user")
public class UserController {
@Resource
private UserServiceImpl userService;
@RequestMapping("login")
public String login(String userName,String userPwd,boolean rememberMe){
try {
userService.checkLogin(userName,userPwd,rememberMe);
System.out.println("------登录成功!");
return "index";
} catch (Exception e) {
System.out.println("------登录失败!");
return "login";
}
}
}
service
@Service
public class UserServiceImpl {
public void checkLogin(String userName, String userPwd,boolean rememberMe) throws Exception {
//Shiro进行认证 ——入口
Subject subject = SecurityUtils.getSubject();
UsernamePasswordToken token = new UsernamePasswordToken(userName,userPwd);
token.setRememberMe(rememberMe);
subject.login(token);
}
}
参考资料
Shiro官方配置: http://shiro.apache.org/spring.html.