【Shiro】Shiro的MVC、SpringBoot整合配置及常用配置

Shiro的配置

导入Shiro依赖库

	<dependency>
		<groupId>org.apache.shiro</groupId>
		<artifactId>shiro‐core</artifactId>
		<version>1.4.1</version>
	</dependency>
	
	<dependency>
		<groupId>org.apache.shiro</groupId>
		<artifactId>shiro‐web</artifactId>
		<version>1.4.1</version>
	</dependency>

	<dependency>
		<groupId>org.apache.shiro</groupId>
		<artifactId>shiro‐spring</artifactId>
		<version>1.4.1</version>
	</dependency>

本博文配置以1.4.1版本为参考,其他版本如有出入请以官方配置为主
官方配置地址在此博文底部

SpringMVC整合Shiro

  • 拦截所有请求
<?xml version="1.0" encoding="UTF‐8"?>
<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>contextConfigLocation</param‐name>
		<param‐value>classpath:spring‐*.xml</param‐value>
	</context‐param>
	<listener>
		<listener‐class>org.springframework.web.context.ContextLoaderListener</listener‐class>
	</listener>
	<servlet>
		<servlet‐name>springMVC</servlet‐name>
		<servlet‐class>org.springframework.web.servlet.DispatcherServlet</servlet‐
	class>
		<init‐param>
			<param‐name>contextConfigLocation</param‐name>
			<param‐value>classpath:spring‐context*.xml</param‐value>
		</init‐param>
	</servlet>
	<servlet‐mapping>
		<servlet‐name>springMVC</servlet‐name>
		<url‐pattern>*.do</url‐pattern>
	</servlet‐mapping>
	<filter>
		<filter‐name>shiroFilter</filter‐name>
		<filter‐class>org.springframework.web.filter.DelegatingFilterProxy</filter‐class>
		<init‐param>
			<param‐name>targetFilterLifecycle</param‐name>
			<param‐value>true</param‐value>
		</init‐param>
	</filter>
	<filter‐mapping>
		<filter‐name>shiroFilter</filter‐name>
		<url‐pattern>/*</url‐pattern>
	</filter‐mapping>
</web‐app>

创建spring-context-shiro.xml
配置shiro

<?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">
<!‐‐shiro过滤器‐‐>
<bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">
	<property name="securityManager" ref="securityManager"></property>
	<!‐‐配置登录页面地址,非必须,默认寻找web项目根路径下的/login.jsp‐‐>
	<property name="loginUrl" value="/login.jsp"></property>
	
	<!‐‐配置登录成功之后跳转的页面路径此配置一般不使用一般在LoginController中处理逻辑‐‐>
	<property name="successUrl" value="/index.jsp"></property>
	<property name="unauthorizedUrl" value="/"></property>
	<property name="filterChainDefinitions">
		<value>/**=anon</value>
	</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>

SpringBoot应用整合Shiro配置

  • SpringBoot默认没有提供对Shiro的自动配置

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;
    }


}
  • 自定义Realm
/**
 * 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;
    }
}

Shiro使用加密认证

@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.boot</groupId>
    <artifactId>spring-boot-starter-cache</artifactId>
</dependency>

<dependency>
    <groupId>net.sf.ehcache</groupId>
    <artifactId>ehcache</artifactId>
</dependency>

<dependency>
    <groupId>org.apache.shiro</groupId>
    <artifactId>shiro-ehcache</artifactId>
    <version>1.4.0</version>
</dependency>
  • 配置缓存策略
    在resources目录下创建一个xml文件(ehcache.xml)
<?xml version="1.0" encoding="UTF-8"?>
<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"/>
            <!--缓存淘汰策略:当缓存空间比较紧张时,我们要存储新的数据进来,就必然要删除一些老的数据
                LRU 最近最少使用
                FIFO 先进先出
                LFU  最少使用
            -->
</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;
}

session管理

  • 配置自定义SessionManager:ShiroConfig.java
@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.

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值