仕上げ史郎のspringboot統合

2を統合するための最も簡単な整頓最近の研究springbootと史郎、。

1、瓶包:

ここでは、親とのjarパッケージのバージョンを統一。

<parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.1.9.RELEASE</version>
</parent>

    <properties>
        <java.version>1.8</java.version>
    </properties>
    
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <!-- jasper是tomcat中使用的JSP引擎 -->
        <dependency>
            <groupId>org.apache.tomcat.embed</groupId>
            <artifactId>tomcat-embed-jasper</artifactId>
        </dependency>

        <!-- 添加 servlet 依赖 -->
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>javax.servlet-api</artifactId>
            <scope>provided</scope>
        </dependency>

        <!-- 添加 jstl -->
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>jstl</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-jdbc</artifactId>
        </dependency>

        <dependency>
            <groupId>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter</artifactId>
            <version>2.1.1</version>
        </dependency>

        <dependency>
            <groupId>tk.mybatis</groupId>
            <artifactId>mapper-spring-boot-starter</artifactId>
            <version>2.1.5</version>
        </dependency>

        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
        </dependency>

        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
        </dependency>

        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid-spring-boot-starter</artifactId>
            <version>1.1.21</version>
        </dependency>

        <!-- shiro相关包 -->
        <dependency>
            <groupId>org.apache.shiro</groupId>
            <artifactId>shiro-spring</artifactId>
            <version>1.4.2</version>
        </dependency>
        <dependency>
            <groupId>org.apache.shiro</groupId>
            <artifactId>shiro-ehcache</artifactId>
            <version>1.4.2</version>
        </dependency>
    </dependencies>

2、設定ファイルには、リソースのapplication.propertiesと史郎キャッシュファイルehcache.xmlをspringboot必要があります。

まず:コメントして設定をapplication.properties、あまりの話ではありません。

#修改服务器端口号和项目根路径
server.port=8080
server.servlet.context-path=/shiro

# 设置包的日志级别为debug(这里demo是我的总包,你可以写任意一个包)
logging.level.demo=debug

#jdbc属性
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/hibernate?useSSL=false&serverTimezone=Hongkong&characterEncoding=utf-8&autoReconnect=true
spring.datasource.username=root
spring.datasource.password=1234

# mybatis 别名扫描
mybatis.type-aliases-package=demo.pojo
# mapper.xml文件位置,如果没有映射文件,请注释掉
mybatis.mapper-locations=classpath:mappers/*.xml

# jsp配置(如果用官方推荐的thymeleaf,就不用写了,有默认值)
spring.mvc.view.prefix=/WEB-INF/jsp/
spring.mvc.view.suffix=.jsp

# springboot 提供多环境配置的机制
spring.profiles.active=dev

そして、ehcache.xmlファイル:

<?xml version="1.0" encoding="UTF-8"?>
<ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:noNamespaceSchemaLocation="http://www.ehcache.org/ehcache.xsd"
         updateCheck="false">

    <diskStore path="D:/tmpdir"/>

    <!--
    缓存配置:
    maxElementsInMemory:内存中最大存放的元素的个数
    eternal:缓存的数据是否永生
    timeToIdleSeconds:闲置多久清除,单位秒
    timeToLiveSeconds:存活多久清除,单位秒
    overflowToDisk: 缓存存储的数据达到maxElementsInMemory限制时是否overflow到磁盘
    maxElementsOnDisk:缓存到硬盘上最大的元素个数
    diskExpiryThreadIntervalSeconds:过期轮询时间,单位秒
    memoryStoreEvictionPolicy:内存存储和清除策略,
        默认三个策略,分别为LRU(最近最少使用)LFU(最常用的)FIFO(先进先出)-->
    <defaultCache
            maxElementsInMemory="1000"
            eternal="false"
            timeToIdleSeconds="120"
            timeToLiveSeconds="120"
            overflowToDisk="true"
            maxElementsOnDisk="10000000"
            diskPersistent="true"
            diskExpiryThreadIntervalSeconds="120"
            memoryStoreEvictionPolicy="LRU"
    />

</ehcache>

3、注釈のJavaとspring.xmlシロ-Bean構成の構成において:

これは、2つのノートを使用しています。

- @Configuration`:声明一个类作为配置类,代替xml文件
- @Bean:声明在方法上,将方法的返回值加入Bean容器,代替`<bean>`标签
@Configuration
public class ShiroConfig {

    /*开启shiro缓存*/
    @Bean
    public EhCacheManager ehCacheManager() {
        EhCacheManager ehCacheManager = new EhCacheManager();
        ehCacheManager.setCacheManagerConfigFile("classpath:ehcache.xml");
        return ehCacheManager;
    }

    /*凭证匹配器:身份认证*/
    @Bean
    public HashedCredentialsMatcher credentialsMatcher() {
        HashedCredentialsMatcher hashedCredentialsMatcher = new HashedCredentialsMatcher();
        hashedCredentialsMatcher.setHashAlgorithmName("md5");
        hashedCredentialsMatcher.setHashIterations(2);
        return hashedCredentialsMatcher;
    }

    /*自定义realm*/
    @Bean
    public UserRealm userRealm(UserService userService) {
        UserRealm userRealm = new UserRealm();
        userRealm.setUserService(userService);
        userRealm.setCredentialsMatcher(credentialsMatcher());
        //userRealm开启缓存
        userRealm.setCachingEnabled(true);
        //开启权限缓存
        userRealm.setAuthorizationCacheName("authorizationCache");
        userRealm.setAuthorizationCachingEnabled(true);
        return userRealm;
    }

    //安全管理器
    //所有与安全有关的操作都会与 SecurityManager 交互;且它管理着所有 Subject;
    //可以看出它是 Shiro 的核心,它负责与后边介绍的其他组件进行交互
    //可以把它看成 DispatcherServlet 前端控制器;
    //SecurityManager 要验证用户身份,那么它需要从 Realm 获取相应的用户进行比较以确定用户身份是否合法
    @Bean
    public DefaultWebSecurityManager securityManager(UserRealm userRealm) {
        DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
        
        //设置自定义Realm.也可以传realm集合。securityManager.setRealms(list)
        
        securityManager.setRealm(userRealm);
        securityManager.setCacheManager(ehCacheManager());
        return securityManager;
    }

    /*shiro拦截器做配置*/
    @Bean
    public ShiroFilterFactoryBean shiroFilter(org.apache.shiro.mgt.SecurityManager securityManager) {
        ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
        shiroFilterFactoryBean.setSecurityManager(securityManager);
        shiroFilterFactoryBean.setLoginUrl("/tologin");
        shiroFilterFactoryBean.setSuccessUrl("/index");
        Map<String, String> filterChainDefinitionMap = new LinkedHashMap<>();
        filterChainDefinitionMap.put("/tologin", "anon");
        filterChainDefinitionMap.put("/login", "anon");
        filterChainDefinitionMap.put("/index", "anon");
        filterChainDefinitionMap.put("/logout", "logout");
        filterChainDefinitionMap.put("/admin/**", "authc");
        filterChainDefinitionMap.put("/user/add", "authc");
        filterChainDefinitionMap.put("/user/**", "authc");
        shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);
        return shiroFilterFactoryBean;
    }

    /*生命周期前置处理器bean*/
    @Bean
    public LifecycleBeanPostProcessor lifecycleBeanPostProcessor() {
        return new LifecycleBeanPostProcessor();
    }

    /*shiro AOP*/
    @Bean
    public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(org.apache.shiro.mgt.SecurityManager securityManager) {
        AuthorizationAttributeSourceAdvisor a = new AuthorizationAttributeSourceAdvisor();
        a.setSecurityManager(securityManager);
        return a;
    }

    /* - Enable Shiro Annotations for Spring-configured beans.  Only run after -->
    <!-- the lifecycleBeanProcessor has run:*/
    /*开启shiro注释,并且需要lifecycleBeanProcessor存在*/
    @Bean
    public DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator() {
        DefaultAdvisorAutoProxyCreator d = new DefaultAdvisorAutoProxyCreator();
        d.setProxyTargetClass(true);
        return d;
    }

}

図4に示すように、構成された、シロ認証プロセスに従ってコードと相まって。

ここに画像を挿入説明
トークンに詰めユーザーによってアップロードされた収集身元情報、コールsubject.login()

@RequestMapping("login")
    public String login(HttpServletRequest request) {
        //用户上传的身份信息
        String username = request.getParameter("username");
        String password = request.getParameter("password");
        String msg = null;
        
        //包装成token
        UsernamePasswordToken token = new UsernamePasswordToken(username, password);
        
        //调用subject.login()
        Subject subject = SecurityUtils.getSubject();
        try {
            subject.login(token);
        } catch (UnknownAccountException e) {
            e.printStackTrace();
            msg = "账号错误";
        } catch (IncorrectCredentialsException e) {
            e.printStackTrace();
            msg = "密码错误";
        } catch (Exception e) {
            e.printStackTrace();
            msg = "其他错误";
        }
        if (null != msg) {
            request.setAttribute("msg", msg);
            return "login";
        }
        
		//下面的代码可以替换成用户身份下的某个角色
        Session session = subject.getSession();
        System.out.println("session = " + session.getClass());
        System.out.println("session = " + session.getId());
        session.setAttribute("roleId", 1);
        return "index";
    }

ユーザ認証が正しい場合、それはメインページに移動しますindex.htmlを

:doGetAuthenticationInfo認証方法の下に取り付けられた
四つのパラメータAuthenticationInfoこのメソッドによって返されるオブジェクトである:
プリンシパル:識別、被験者のすなわち識別属性は。データベースからの一般的。
資格証明書:証明書/バウチャー。ユーザ入力。
credentialsSalt:暗号化されたソルト値
realmNameに:realmNameに

UserRealm.class:

public class UserRealm extends AuthorizingRealm {

    private UserService userService;

    public void setUserService(UserService userService) {
        this.userService = userService;
    }

    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
        Subject subject = SecurityUtils.getSubject();
        Session session = subject.getSession();
        System.out.println("roleId=" + session.getAttribute("roleId"));
        System.out.println("session = " + session.getId());
        //通过查库得到角色与权限数据 userService.getPermsByRoleId(roleId)
        SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
        info.addRoles(userService.getRoles());
        info.addStringPermissions(userService.getPerms());
        System.out.println("==========授权==========");
        return info;
    }

    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
        String username = token.getPrincipal().toString();
        // User user = userService.findByUsername(username);
        // 数据库中查询出的加密过的密码 原值=admin
        String password = "d0fbeefddc1cb9b0f9b4bcdd5b50b8cc";
        // 可以从数据库中查询
        String salt = "skeye";
        //
        User user = new User();
        user.setUsername(username);
        System.out.println("==========认证");

       // 参数依次:principal,hashedCredentials,credentialsSalt,realmName
        return new SimpleAuthenticationInfo
                (user, password, ByteSource.Util.bytes(salt), getName());
    }
	
    public void clearCachedAuthorizationInfo(PrincipalCollection principals) {
        super.clearCachedAuthorizationInfo(principals);
    }
}

5、権限認証プロセス:

ここに画像を挿入説明
同行コード:
対応するコントローラメソッドの機能を同行するために必要な権限

@Controller
@RequestMapping()
public class AuthController {

    @RequestMapping("/admin/add")
    @RequiresPermissions("/admin/add")
    public String addAdmin() {
        return "adminAdd";
    }

    @RequestMapping("/user/add")
    @RequiresPermissions("/user/add")
    public String addUser() {
        return "userAdd";
    }

}

コードを検証するdoGetAuthenticationInfo方法は、上記userRealm.classで結合されています。

6、スイッチの役割

(史郎キャッシュメカニズムを使用すると、アクセス許可のキャッシュを持っている場合、それはライブラリのアップデートキャッシュをチェックして行くことはありませんですので、クリーンアップキャッシュ権情報)最後に、ログイン状態の下で機能スイッチの役割を実現付けます。
まずloginAgain方法を添付:このメソッドは、毎回のスイッチングを実行します。
ここでは明確なキャッシュ方式であるUserRealmです。

@RequestMapping("loginAgain")
    public String login2(HttpServletRequest request) {
        PrincipalCollection principals = SecurityUtils.getSubject().getPrincipals();
        UserRealm userRealm = MyApplicationContextUtils.getBean(UserRealm.class);
        // 清除授权缓存
        userRealm.clearCachedAuthorizationInfo(principals);
        System.out.println(" ==========清理授权缓存==========");
        return "index";
    }

AuthorizingRealm.classで史郎明確なキャッシュ機能、実際に達成されて、私たちはそれを呼び出す:
史郎出典:

    protected void clearCachedAuthorizationInfo(PrincipalCollection principals) {
        if (principals != null) {
            Cache<Object, AuthorizationInfo> cache = this.getAvailableAuthorizationCache();
            if (cache != null) {
                Object key = this.getAuthorizationCacheKey(principals);
                cache.remove(key);
            }

        }
    }

これは、保護された方法です。パッケージのFeizi異なる種類のは、私たちがこのメソッドをオーバーライドする必要があり、呼び出すことはできません。私達はちょうどUseRealm方法はAuthorizingRealm、親クラスのメソッドへの直接参照を継承しています。

 public void clearCachedAuthorizationInfo(PrincipalCollection principals) {
        super.clearCachedAuthorizationInfo(principals);
    }

最後に、問題がある豆工場豆に登録したクラスあるUserRealmを取得する方法である:
内部クラスを開始するメソッドの戻り値は、私たちがBeanクラスを介してそれを得ることができ、実際にたBeanFactory実装クラスのサブクラスです:
springboot下回りますユーティリティクラスによって保存された内部クラスConfigurableApplicationContextの戻り値の起動方法。

@SpringBootApplication
public class ShiroApp {
    public static void main(String[] args) {
        ConfigurableApplicationContext applicationContext = SpringApplication.run(ShiroApp.class);
        MyApplicationContextUtils.setApplicationContext(applicationContext);
    }
}

ツールコード:ランダムのような

public class MyApplicationContextUtils {

    private static ApplicationContext applicationContext;

    public static void setApplicationContext(ApplicationContext applicationContext) {
        MyApplicationContextUtils.applicationContext = applicationContext;
    }
    public static <T> T getBean(Class<T> clazz) {

        return applicationContext.getBean(clazz);
    }
}

[OK]を、簡単なここでの設定、および更新後にプロジェクトを完了します。

詳細はお問い合わせくださいます。https://www.w3cschool.cn/shiro/

公開された14元の記事 ウォンの賞賛0 ビュー318

おすすめ

転載: blog.csdn.net/qq_38205881/article/details/104287586