shiro集成 --《springboot与shiro整合》

Posted zls1218

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了 shiro集成 --《springboot与shiro整合》相关的知识,希望对你有一定的参考价值。

 

2.1 引入shiro相关依赖

     <dependency>  
            <groupId>commons-logging</groupId>  
            <artifactId>commons-logging</artifactId>  
            <version>1.1.3</version>  
        </dependency>  
        <dependency>  
            <groupId>org.apache.shiro</groupId>  
            <artifactId>shiro-core</artifactId>  
            <version>1.2.2</version>  
        </dependency>  
         <dependency>  
            <groupId>org.apache.shiro</groupId>  
            <artifactId>shiro-web</artifactId>  
            <version>1.2.2</version>  
        </dependency>   

 

2.2  自定义Realm  

@Component
public class UserRealm extends AuthorizingRealm{
    
    
    @Autowired
    private UserService userService;
    
    /**
     * 授权
     * @param principals
     * @return
     */
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(
            PrincipalCollection principals) {
        
        String username = (String) principals.getPrimaryPrincipal();
        SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo();
        //在数据库中查询用户拥有的角色/权限
        authorizationInfo.setRoles(userService.findRoles(username));
        authorizationInfo.setStringPermissions(userService.findPermissions(username));
        return authorizationInfo;
    }

    
    /**
     * 验证
     */
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(
            AuthenticationToken token) throws AuthenticationException {

        String username = (String) token.getPrincipal();
        User user = userService.findByUsername(username); 
        if(user == null){
            throw new UnknownAccountException(); //没找到账号
        }
        
        if(Boolean.TRUE.equals(user.getLocked())){
            throw new LockedAccountException(); //账号被锁定
        }
        
        SimpleAuthenticationInfo authenticationInfo = new SimpleAuthenticationInfo(
                user.getUsername(),
                user.getPassword(),
                ByteSource.Util.bytes(user.getCredentialsSalt()), //salt = username+salt
                getName());
            
        
        return authenticationInfo;
    }

}

 

2.3 ShiroConfig 

@Configuration
public class ShiroConfig {
    
    @Bean  
    public ShiroFilterFactoryBean shiroFilter(SecurityManager securityManager){
        ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
        shiroFilterFactoryBean.setSecurityManager(securityManager);
        //拦截器.  
        Map<String,String> filterChainDefinitionMap = new LinkedHashMap<String,String>(); 
        //配置退出过滤器,其中的具体的退出代码Shiro已经替我们实现了  
        filterChainDefinitionMap.put("logout", "logout");
        filterChainDefinitionMap.put("/user/login", "anon");
        // authc:所有url都必须认证通过才可以访问; anon:所有url都都可以匿名访问
        filterChainDefinitionMap.put("/user/**", "anon");
filterChainDefinitionMap.put("/test/**", "authc");
filterChainDefinitionMap.put("/page/**", "authc"); // 如果不设置默认会自动寻找Web工程根目录下的"/login.jsp"页面 shiroFilterFactoryBean.setLoginUrl("/login.html");
        shiroFilterFactoryBean.setUnauthorizedUrl("/page/fail.html");//未授权跳转
        //登录成功跳转的链接 (这个不知道怎么用,我都是自己实现跳转的)
        shiroFilterFactoryBean.setSuccessUrl("/page/main.html");
        shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);
        return shiroFilterFactoryBean;
    }
    
    /**  
     * 凭证匹配器  
     * 由于我们的密码校验交给Shiro的SimpleAuthenticationInfo进行处理了  
     * @return  
     */  
    @Bean  
    public HashedCredentialsMatcher hashedCredentialsMatcher() {  
        HashedCredentialsMatcher hashedCredentialsMatcher = new HashedCredentialsMatcher();  
        hashedCredentialsMatcher.setHashAlgorithmName("md5");//散列算法:这里使用MD5算法;  
        hashedCredentialsMatcher.setHashIterations(2);//散列的次数,比如散列两次,相当于 md5(md5(""));  
        return hashedCredentialsMatcher;  
    }  
    
    
    @Bean  
    public UserRealm myShiroRealm() {  
        UserRealm myShiroRealm = new UserRealm(); 
//使用加密
myShiroRealm.setCredentialsMatcher(hashedCredentialsMatcher());
        return myShiroRealm;  
    }  
    
    @Bean  
    public SecurityManager securityManager() {  
        DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();  
        securityManager.setRealm(myShiroRealm());  
        return securityManager;  
    }
    
    
    @Bean
    public LifecycleBeanPostProcessor lifecycleBeanPostProcessor(){
        return new LifecycleBeanPostProcessor();
    }
    
    /** 
     * 注册全局异常处理 
     * @return 
     */  
    @Bean(name = "exceptionHandler")  
    public HandlerExceptionResolver handlerExceptionResolver() {  
        return new ExceptionHandler();  
    }
    
    
}

 

2.4 创建UserController

@RestController
@RequestMapping("/user")
public class UserController {
    
    @Autowired
    private UserService userService;
    
    @RequestMapping("/login")
    public ModelAndView login(User loginUser,ServletRequest request){
        
        ModelAndView view = new ModelAndView();
        Subject subject = SecurityUtils.getSubject();
        UsernamePasswordToken token = new UsernamePasswordToken(loginUser.getUsername(),loginUser.getPassword());
        if(!subject.isAuthenticated()){
            
            subject.login(token);
        }
        //获取上一次请求路径
        SavedRequest savedRequest = WebUtils.getSavedRequest(request);
        String url = "";
        if(savedRequest != null){
            url = savedRequest.getRequestUrl();
        }else{
            url = "/page/main.html";
        }
        
        view.setViewName("redirect:"+url);
        return view;
    }
    
    @RequestMapping("/register")
    public ModelAndView add(User user){
        ModelAndView view = new ModelAndView();
        userService.createUser(user);
        view.setViewName("redirect:/login.html");
        return view;
    }
    
    @RequestMapping("/logout")
    public String logout(User loginUser){
        Subject subject = SecurityUtils.getSubject();
        subject.logout();
        return "已注销";
    }
}

 

UserService

    @Override
    public Long createUser(User user) {
        PasswordHelper.encryptPassword(user);
        return userDao.createUser(user);
    }

 

PasswordHelper (加密,保存到数据库的时候使用)

    private static RandomNumberGenerator randomNumberGenerator = new SecureRandomNumberGenerator();
    //这些要与Realm中的一致
    private static String algorithmName = "md5";
    private final static int hashIterations = 2;

    static public  void encryptPassword(User user) {
        //加盐
        user.setSalt(randomNumberGenerator.nextBytes().toHex());
        String newPassword = new SimpleHash(algorithmName, user.getPassword(),
                ByteSource.Util.bytes(user.getCredentialsSalt()),
                hashIterations).toHex();
        user.setPassword(newPassword);
    }

 

下面我们来测试一下吧 (页面代码这里就不写了)

技术分享图片

 

我们先访问  http://localhost:8080/page/main.html  由于在ShiroConfig中设置了 page 目录下面的所有文件都需要认真通过才能访问

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

这时候会跳转到登录页面

技术分享图片

 

先注册一个用户

技术分享图片

查看数据库

技术分享图片

 

 这时候在登录就可以访问到首页了

技术分享图片

 

很简单的一个用户认证功能,下面我们继续完善

源码点这里

 





以上是关于 shiro集成 --《springboot与shiro整合》的主要内容,如果未能解决你的问题,请参考以下文章

shiro集成Spring

Springboot学习Shiro快速入门及与SpringBoot集成

Shiro功能应用--Shiro集成RedisTemplate(SDR)

SpringBoot 集成 Shiro:使用Shiro的角色管理

SpringBoot集成Shiro

freemarker集成shiro标签