1. 程式人生 > 實用技巧 >spring boot與shiro實現單點登入

spring boot與shiro實現單點登入

1. Shiro框架簡介

Apache Shiro是一個強大且易用的Java安全框架,執行身份驗證、授權、密碼學和會話管理。使用Shiro的易於理解的API,您可以快速、輕鬆地獲得任何應用程式,從最小的移動應用程式到最大的網路和企業應用程式。

1、 Authentication 認證 ---- 使用者登入

2、 Authorization 授權 --- 使用者具有哪些許可權

3、 Cryptography 安全資料加密

4、 Session Management 會話管理

5、 Web Integration web系統整合

6、 Interations 整合其它應用,spring、快取框架

2.匯入jar包

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

3.建立ShiroConfig配置類

package org.jcut.config;

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

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; /** * Shiro的配置類 * @author lenovo * */ @Configuration public class
ShiroConfig { /** * 建立ShiroFilterFactoryBean */ @Bean public ShiroFilterFactoryBean getShiroFilterFactoryBean(@Qualifier("securityManager")DefaultWebSecurityManager securityManager){ ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean(); //設定安全管理器 shiroFilterFactoryBean.setSecurityManager(securityManager); //新增Shiro內建過濾器 /** * Shiro內建過濾器,可以實現許可權相關的攔截器 * 常用的過濾器: * anon: 無需認證(登入)可以訪問 * authc: 必須認證才可以訪問 * user: 如果使用rememberMe的功能可以直接訪問 * perms: 該資源必須得到資源許可權才可以訪問 * role: 該資源必須得到角色許可權才可以訪問 */ Map<String,String> filterMap = new LinkedHashMap<String,String>(); /*filterMap.put("/add", "authc"); filterMap.put("/update", "authc");*/ //放行login.html頁面 filterMap.put("/login", "anon"); filterMap.put("/index.html", "anon"); //放行靜態資原始檔和不用攔截的訪問 filterMap.put("/js/**", "anon"); filterMap.put("/css/**", "anon"); filterMap.put("/big/**", "anon"); filterMap.put("/fonts/**", "anon"); filterMap.put("/images/**", "anon"); filterMap.put("/Products/**", "anon"); filterMap.put("/imgs/**", "anon"); filterMap.put("/comment/**", "anon"); filterMap.put("/Product_Detailed.html", "anon"); filterMap.put("/commodity/**", "anon"); filterMap.put("/pack/**", "anon"); filterMap.put("/type/**", "anon"); filterMap.put("/detail/**", "anon"); filterMap.put("/collect/selectBycId", "anon"); filterMap.put("/small/**", "anon"); filterMap.put("/user/select", "anon"); //授權過濾器 filterMap.put("/**", "authc"); //修改調整的登入頁面 shiroFilterFactoryBean.setLoginUrl("/login.htm"); //設定未授權提示頁面 shiroFilterFactoryBean.setUnauthorizedUrl("/login.htm"); shiroFilterFactoryBean.setFilterChainDefinitionMap(filterMap); return shiroFilterFactoryBean; } /** * 建立DefaultWebSecurityManager */ @Bean(name="securityManager") public DefaultWebSecurityManager getDefaultWebSecurityManager(@Qualifier("userRealm")UserRealm userRealm){ DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager(); //關聯realm securityManager.setRealm(userRealm); return securityManager; } /** * 建立Realm */ @Bean(name="userRealm") public UserRealm getRealm(){ return new UserRealm(); } }

4.建立認證授權類

package org.jcut.config;
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.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.jcut.bean.User;
import org.jcut.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;


/**
 * 自定義Realm
 * @author lenovo
 *
 */
public class UserRealm extends AuthorizingRealm{

    /**
     * 執行授權邏輯
     */
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection arg0) {
        System.out.println("執行授權邏輯");
        return null;
    }
    
    @Autowired
    private UserService userSerivce;

    /**
     * 執行認證邏輯
     */
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken arg0) throws AuthenticationException {
        System.out.println("執行認證邏輯");
        
        ///編寫shiro判斷邏輯,判斷使用者名稱和密碼
        //1.判斷使用者名稱
        UsernamePasswordToken token = (UsernamePasswordToken)arg0;
        User user=new User();
        user.setTel(token.getUsername());
        user.setPwd(String.valueOf(token.getPassword()));
        List<User> list=userSerivce.select(user);
        if(list.size()==0){
            //使用者名稱不存在
            return null;//shiro底層會丟擲UnKnowAccountException
        }
        
        //2.判斷密碼
       return new SimpleAuthenticationInfo(list.get(0),token.getPassword(),token.getUsername());
    }


}

5.登入Controller

    @RequestMapping(value="/select",params = {"pwd","tel"})
    public Object select(User user) {
        user.setPwd(MD5Util.encode2hex(user.getPwd()));
        /**
         * 使用Shiro編寫認證操作
         */
        //1.獲取Subject
        Subject subject = SecurityUtils.getSubject();
        
        //2.封裝使用者資料
        UsernamePasswordToken token = new UsernamePasswordToken(user.getTel(),user.getPwd());
        
        
            try {
                subject.login(token);
                User user1=service.select(user).get(0);
                List list=new ArrayList<User>();
                list.add(user1);
                redisTemplate.opsForValue().set(user1.getId(), list, 1l, TimeUnit.HOURS);
                data.setData(user1.getId());
                data.setStatus("1");
                data.setMsg("登陸成功!");
            }catch(Exception e) {

                data.setData("0");
                data.setStatus("0");
                data.setMsg("登陸失敗!");
            }
        
        return data;
    }