(二) 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"); 

這時候會跳轉到登錄頁面

 

先注冊一個用戶

查看數據庫

 

 這時候在登錄就可以訪問到首頁了

 

很簡單的一個用戶認證功能,下面我們繼續完善

源碼點這里

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM