spring boot引入shiro进行登陆认证

发布时间:2018-07-04 浏览次数:2644 文章来源:个人博客

最近在用spring boot 做开发,而shiro是一个权限认证工具,所以将shiro整合到springboot中。

首先,maven引入shiro包。这里引入的是1.4的。

<dependency>
   <groupId>org.apache.shiro</groupId>
   <artifactId>shiro-spring</artifactId>
   <version>1.4.0</version>
</dependency>

引入包后,接下来就是进行配置了。

在配置目录下,新建ShiroConfig.java文件,代码:

package com.company.test.config;

import org.apache.shiro.authc.credential.HashedCredentialsMatcher;
import org.apache.shiro.mgt.SecurityManager;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.util.LinkedHashMap;
import java.util.Map;

@Configuration
public class ShiroConfig {

    @Bean
    public ShiroFilterFactoryBean shirFilter(@Qualifier("securityManager") SecurityManager manager) {

        System.out.println("ShiroConfiguration.shirFilter()");

        ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();

        shiroFilterFactoryBean.setSecurityManager(manager);

        //拦截器.

        Map<String,String> filterChainDefinitionMap = new LinkedHashMap<String,String>();

        // 配置不会被拦截的链接 顺序判断

        filterChainDefinitionMap.put("/h/**", "anon");

        //配置退出 过滤器,其中的具体的退出代码Shiro已经替我们实现了

        filterChainDefinitionMap.put("/logout", "logout");

        //<!-- 过滤链定义,从上向下顺序执行,一般将/**放在最为下边 -->:这是一个坑呢,一不小心代码就不好使了;

        //<!-- authc:所有url都必须认证通过才可以访问; anon:所有url都都可以匿名访问-->

        filterChainDefinitionMap.put("/**", "authc");

        // 如果不设置默认会自动寻找Web工程根目录下的"/login.jsp"页面

        shiroFilterFactoryBean.setLoginUrl("/h/login");

        // 登录成功后要跳转的链接

        shiroFilterFactoryBean.setSuccessUrl("/index");



        //未授权界面;

        shiroFilterFactoryBean.setUnauthorizedUrl("/403");

        shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);

        return shiroFilterFactoryBean;

    }


    //这里设置安全信息认证的方式,由用户自己定义。怎么定义呢,就是根据MyShiroRealm重写。
    @Bean
    public MyShiroRealm myShiroRealm(){
        //MyShiroRealm是自己建立的类
        MyShiroRealm myShiroRealm = new MyShiroRealm();
        myShiroRealm.setCredentialsMatcher(hashedCredentialsMatcher());
        return myShiroRealm;

    }




    //这里主要是设置Realm 就是认证的安全数据
    @Bean
    public SecurityManager securityManager(){

        DefaultWebSecurityManager securityManager =  new DefaultWebSecurityManager();
        //SecurityManager要验证用户身份,那么它需要从Realm获取相应的用户进行比较以确定用户身份是否合法;
        //也需要从Realm得到用户相应的角色/权限进行验证用户是否能进行操作;可以把Realm看成DataSource,即安全数据源
        securityManager.setRealm(myShiroRealm());

        return securityManager;

    }

    /*
     * 凭证匹配器
     * (由于我们的密码校验交给Shiro的SimpleAuthenticationInfo进行处理了
     *  所以我们需要修改下doGetAuthenticationInfo中的代码;)
    * @return
     */
    @Bean
    public HashedCredentialsMatcher hashedCredentialsMatcher(){
        HashedCredentialsMatcher hashedCredentialsMatcher = new HashedCredentialsMatcher();

        hashedCredentialsMatcher.setHashAlgorithmName("md5");//散列算法:这里使用MD5算法;
//        hashedCredentialsMatcher.setHashIterations(2);//散列的次数,比如散列两次,相当于 md5(md5(""));

        return hashedCredentialsMatcher;
    }
}

上面的是基础的配置,然后我们需要配置MyShiroRealm类,代码如下:

package com.company.test.config;

import com.company.test.model.User;
import com.company.test.server.UserService;
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.authz.AuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.util.ByteSource;
import org.springframework.beans.factory.annotation.Autowired;

public class MyShiroRealm extends AuthorizingRealm {

    @Autowired
    private UserService userService;

    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
        return null;
    }

    /**
     * 认证信息.(身份验证)
     * :
     * Authentication 是用来验证用户身份
     * @param token
     * @return
     * @throws AuthenticationException
     */
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
        System.out.println("MyShiroRealm.doGetAuthenticationInfo()");

        //获取用户的输入的账号.
        String username = (String)token.getPrincipal();
        //取查询数据库中用户的信息
        User userInfo = userService.findUser(username);
        if(userInfo == null){
            return null;
        }
        SimpleAuthenticationInfo authenticationInfo = new SimpleAuthenticationInfo(
                userInfo, //用户名
                userInfo.getPassword(), //密码
                getName()  //realm name
        );

        return authenticationInfo;
    }
}

至此,shiro基本上算是完成了。当用户输入账号密码时候,即可调用验证代码:

try{
    UsernamePasswordToken token = new UsernamePasswordToken(name, pwd);
    //login方法提交认证,会执行CustomerShiroRealm中的doGetAuthenticationInfo认证方法
    SecurityUtils.getSubject().login(token);   
    //认证通过
    return true;
}catch (AuthenticationException e){

    e.getStackTrace();
    System.out.println(e.getMessage());
    return false;
}catch (Exception e){
    e.printStackTrace();
    return false;
}


key-word
java shiro spring boot spring boot shiro