SpringBoot学习-(十七)SpringBoot整合Shiro

来源:互联网 发布:12306手机购票软件 编辑:程序博客网 时间:2024/06/02 04:37

基本步骤:

  1. 添加pom文件依赖
  2. 书写自定义的realm
  3. 配置shiro
  4. 控制层使用

项目目录结构:

这里写图片描述


1.添加pom文件依赖

<!-- spring整合shiro --><!-- maven会自动添加shiro-core,shiro-web依赖 --><dependency>    <groupId>org.apache.shiro</groupId>    <artifactId>shiro-spring</artifactId>    <version>1.3.2</version></dependency>

2.书写自定义realm

package com.ahut.shiro;import java.util.ArrayList;import java.util.List;import org.apache.shiro.authc.AuthenticationException;import org.apache.shiro.authc.AuthenticationInfo;import org.apache.shiro.authc.AuthenticationToken;import org.apache.shiro.authc.SimpleAuthenticationInfo;import org.apache.shiro.authc.UsernamePasswordToken;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;/** *  * @ClassName: MyRealm * @Description: 自定义realm * @author cheng * @date 2017年10月9日 上午10:54:00 */public class MyRealm extends AuthorizingRealm {    /**     * 用于认证     */    @Override    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {        System.out.println("使用了自定义的realm,用户认证...");        System.out.println("用户名:" + ((UsernamePasswordToken) token).getUsername());        System.out.println("密码:" + new String(((UsernamePasswordToken) token).getPassword()));        // 模拟账号不存在        // if (true) {        // throw new UnknownAccountException();        // }        // 获取用户名        String userName = (String) token.getPrincipal();        // 依据用户名去数据库查询        // 模拟从数据库中查询出来的散列值密码        String password = "36f2dfa24d0a9fa97276abbe13e596fc";        // 查询到了数据,验证密码是否正确        // 密码正确,认证通过        // 密码错误,认证失败        // 没有查询到数据,认证失败        // 模拟从数据库中获取salt        String salt = "qwerty";        return new SimpleAuthenticationInfo(userName, password, ByteSource.Util.bytes(salt), this.getName());    }    /**     * 用于授权     */    @Override    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {        System.out.println("使用了自定义的realm,用户授权...");        // 获取用户名        // String userName = (String) principals.getPrimaryPrincipal();        // 依据用户名在数据库中查找权限信息        // 角色        List<String> roles = new ArrayList<>();        roles.add("admin");        roles.add("user");        // 权限        List<String> permissions = new ArrayList<>();        permissions.add("admin:select");        permissions.add("admin:delete");        SimpleAuthorizationInfo simpleAuthorizationInfo = new SimpleAuthorizationInfo();        simpleAuthorizationInfo.addStringPermissions(permissions);        simpleAuthorizationInfo.addRoles(roles);        return simpleAuthorizationInfo;    }}

3.配置shiro

package com.ahut.config;import java.util.LinkedHashMap;import java.util.Map;import org.apache.shiro.mgt.SecurityManager;import org.apache.shiro.spring.web.ShiroFilterFactoryBean;import org.apache.shiro.web.mgt.DefaultWebSecurityManager;import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.Configuration;import com.ahut.shiro.MyRealm;/** *  * @ClassName: ShiroConfig * @Description: spring整合shiro配置 * @author cheng * @date 2017年10月10日 上午9:46:43 */@Configurationpublic class ShiroConfig {    /**     *      * @Title: createMyRealm     * @Description: 自定义的realm     * @return     */    @Bean    public MyRealm createMyRealm() {        return new MyRealm();    }    /**     *      * @Title: securityManager     * @Description: 注入自定义的realm     * @Description: 注意方法返回值SecurityManager为org.apache.shiro.mgt.SecurityManager     *               ,不要导错包     * @return     */    @Bean    public SecurityManager securityManager() {        DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();        securityManager.setRealm(createMyRealm());        return securityManager;    }    /**     *      * @Title: shirFilter     * @Description: Shiro 的Web过滤器     * @param securityManager     * @return     */    @Bean    public ShiroFilterFactoryBean shirFilter(SecurityManager securityManager) {        ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();        shiroFilterFactoryBean.setSecurityManager(securityManager);        // 如果不设置默认会自动寻找Web工程根目录下的"/login.jsp"页面        shiroFilterFactoryBean.setLoginUrl("/userLogin");        // 登录成功后要跳转的链接,建议不配置,shiro认证成功自动到上一个请求路径        shiroFilterFactoryBean.setSuccessUrl("/index");        // 未授权界面,指定没有权限操作时跳转页面        shiroFilterFactoryBean.setUnauthorizedUrl("/403");        // 过滤器        Map<String, String> filterChainDefinitionMap = new LinkedHashMap<String, String>();        // 配置不会被过滤的链接 顺序判断        // 过虑器链定义,从上向下顺序执行,一般将/**放在最下边        // 对静态资源设置匿名访问        // anon:所有url都都可以匿名访问        filterChainDefinitionMap.put("/static/**", "anon");        // 配置退出 过滤器,其中的具体的退出代码Shiro已经替我们实现了        filterChainDefinitionMap.put("/logout", "logout");        // authc:所有url都必须认证通过才可以访问        filterChainDefinitionMap.put("/**", "authc");        shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);        return shiroFilterFactoryBean;    }}

代码说明:
1.自定义的realm和注入自定义的realm相当于以前的shiro.ini文件

#自定义的realmmyRealm=com.ahut.test.MyRealm# 注入自定义的realmsecurityManager.realms=$myRealm

2.ShiroFilterFactoryBean相当于以下xml配置

<!-- web.xml中shiro的filter对应的bean --><!-- Shiro 的Web过滤器 --><bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">    <property name="securityManager" ref="securityManager" />    <!-- loginUrl认证提交地址,如果没有认证将会请求此地址进行认证,请求此地址将由formAuthenticationFilter进行表单认证 -->    <property name="loginUrl" value="/login.action" />    <!-- 认证成功统一跳转到first.action,建议不配置,shiro认证成功自动到上一个请求路径 -->    <property name="successUrl" value="/first.action"/>    <!-- 通过unauthorizedUrl指定没有权限操作时跳转页面-->    <property name="unauthorizedUrl" value="/refuse.jsp" />    <!-- 自定义filter配置 -->    <property name="filters">        <map>            <!-- 将自定义 的FormAuthenticationFilter注入shiroFilter中-->            <entry key="authc" value-ref="formAuthenticationFilter" />        </map>    </property>    <!-- 过虑器链定义,从上向下顺序执行,一般将/**放在最下边 -->    <property name="filterChainDefinitions">        <value>            <!-- 对静态资源设置匿名访问 -->            /images/** = anon            /js/** = anon            /styles/** = anon            <!-- 验证码,可匿名访问 -->            /validatecode.jsp = anon            <!-- 请求 logout.action地址,shiro去清除session-->            /logout.action = logout            <!--商品查询需要商品查询权限 ,取消url拦截配置,使用注解授权方式 -->            <!-- /items/queryItems.action = perms[item:query]            /items/editItems.action = perms[item:edit] -->            <!-- 配置记住我或认证通过可以访问的地址 -->            /index.jsp  = user            /first.action = user            /welcome.jsp = user            <!-- /** = authc 所有url都必须认证通过才可以访问-->            /** = authc            <!-- /** = anon所有url都可以匿名访问 -->        </value>    </property></bean><!-- securityManager安全管理器 --><bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">    <property name="realm" ref="customRealm" />    <!-- 注入缓存管理器 -->    <property name="cacheManager" ref="cacheManager"/>    <!-- 注入session管理器 -->    <property name="sessionManager" ref="sessionManager" />    <!-- 记住我 -->    <property name="rememberMeManager" ref="rememberMeManager"/>    </bean><!-- realm --><bean id="customRealm" class="cn.itcast.ssm.shiro.CustomRealm">    <!-- 将凭证匹配器设置到realm中,realm按照凭证匹配器的要求进行散列 -->    <property name="credentialsMatcher" ref="credentialsMatcher"/></bean><!-- 凭证匹配器 --><bean id="credentialsMatcher"    class="org.apache.shiro.authc.credential.HashedCredentialsMatcher">    <property name="hashAlgorithmName" value="md5" />    <property name="hashIterations" value="1" /></bean><!-- 缓存管理器 --><bean id="cacheManager" class="org.apache.shiro.cache.ehcache.EhCacheManager">    <property name="cacheManagerConfigFile" value="classpath:shiro-ehcache.xml"/></bean><!-- 会话管理器 --><bean id="sessionManager" class="org.apache.shiro.web.session.mgt.DefaultWebSessionManager">     <!-- session的失效时长,单位毫秒 -->     <property name="globalSessionTimeout" value="600000"/>     <!-- 删除失效的session -->     <property name="deleteInvalidSessions" value="true"/></bean><!-- 自定义form认证过虑器 --><!-- 基于Form表单的身份验证过滤器,不配置将也会注册此过虑器,表单中的用户账号、密码及loginurl将采用默认值,建议配置 --><bean id="formAuthenticationFilter"     class="cn.itcast.ssm.shiro.CustomFormAuthenticationFilter ">    <!-- 表单中账号的input名称 -->    <property name="usernameParam" value="username" />    <!-- 表单中密码的input名称 -->    <property name="passwordParam" value="password" />    <!-- 记住我input的名称 -->    <property name="rememberMeParam" value="rememberMe"/></bean><!-- rememberMeManager管理器,写cookie,取出cookie生成用户信息 --><bean id="rememberMeManager" class="org.apache.shiro.web.mgt.CookieRememberMeManager">    <property name="cookie" ref="rememberMeCookie" /></bean><!-- 记住我cookie --><bean id="rememberMeCookie" class="org.apache.shiro.web.servlet.SimpleCookie">    <!-- rememberMe是cookie的名字 -->    <constructor-arg value="rememberMe" />    <!-- 记住我cookie生效时间30天 -->    <property name="maxAge" value="2592000" /></bean>

4.控制层使用

package com.ahut.action;import java.util.Map;import javax.servlet.http.HttpServletRequest;import org.apache.shiro.SecurityUtils;import org.apache.shiro.authc.DisabledAccountException;import org.apache.shiro.authc.ExcessiveAttemptsException;import org.apache.shiro.authc.ExpiredCredentialsException;import org.apache.shiro.authc.IncorrectCredentialsException;import org.apache.shiro.authc.LockedAccountException;import org.apache.shiro.authc.UnknownAccountException;import org.apache.shiro.authc.UsernamePasswordToken;import org.apache.shiro.subject.Subject;import org.springframework.web.bind.annotation.RequestMapping;import org.springframework.web.bind.annotation.RestController;/** *  * @ClassName: ShiroAction * @Description: shiro控制层 * @author cheng * @date 2017年10月10日 上午10:18:21 */@RestControllerpublic class ShiroAction {    /**     *      * @Title: userLogin     * @Description: 用户登录     * @return     */    @RequestMapping(value = "/userLogin")    public String userLogin(String username, String password) {        // 以下部分在配置阶段就已经完成,可以直接使用        // 读取配置文件        // Factory<SecurityManager> factory = new IniSecurityManagerFactory("classpath:shiro.ini");        // 获取SecurityManager的实例        // SecurityManager securityManager = factory.getInstance();        // 把 securityManager 的实例绑定到 SecurityUtils 上        // SecurityUtils.setSecurityManager(securityManager);        System.out.println(username + ":" + password);        Subject subject = SecurityUtils.getSubject();        // 自己创建一个令牌,输入用户名和密码        UsernamePasswordToken usernamePasswordToken = new UsernamePasswordToken(username, password);        try {            subject.login(usernamePasswordToken);            System.out.println("身份认证成功!");        } catch (UnknownAccountException e) {            e.printStackTrace();            System.out.println("账号不存在!");        } catch (LockedAccountException e) {            e.printStackTrace();            System.out.println("账号被锁定!");        } catch (DisabledAccountException e) {            e.printStackTrace();            System.out.println("账号被禁用!");        } catch (IncorrectCredentialsException e) {            e.printStackTrace();            System.out.println("凭证/密码错误!");        } catch (ExpiredCredentialsException e) {            e.printStackTrace();            System.out.println("凭证/密码过期!");        } catch (ExcessiveAttemptsException e) {            e.printStackTrace();            System.out.println("登录失败次数过多!");        }        // 是否认证通过        boolean isAuthenticated1 = subject.isAuthenticated();        System.out.println("登录后,是否认证通过:" + isAuthenticated1);        // 退出        subject.logout();        // 是否认证通过        boolean isAuthenticated2 = subject.isAuthenticated();        System.out.println("退出登录后,是否认证通过:" + isAuthenticated2);        return "处理登录";    }}
原创粉丝点击