1. 程式人生 > >上手spring boot專案(二)之spring boot整合shiro安全框架

上手spring boot專案(二)之spring boot整合shiro安全框架

題記:在學習了springboot和thymeleaf之後,想完成一個專案練練手,於是使用springboot+mybatis和thymeleaf完成一個部落格系統,在完成的過程中出現的一些問題,將這些問題記錄下來,作為自己的學習心得。在這先感謝群主TyCoding的Tumo專案,雖然本人實在太菜了,好些地方看不懂,但還是使我受益匪淺。


 

shiro作為一個小巧靈活的安全框架,在認證和授權方面簡約但又不簡單,十分容易上手使用。下面是整合shiro的具體流程。

1.新增依賴

 1 <!--shiro和spring整合-->
 2 <dependency>
 3       <groupId>org.apache.shiro</groupId>
 4       <artifactId>shiro-spring</artifactId>
 5       <version>1.3.2</version>
 6 </dependency>
 7 <!--shiro核心包-->
 8 <dependency>
 9       <groupId>org.apache.shiro</groupId>
10        <artifactId>shiro-core</artifactId>
11        <version>1.3.2</version>
12 </dependency>

2.在springboot控制檯中新增基礎包的掃描和實體類的掃描註解

由於本人實在粗心,用try,catch將這個錯誤包起來了,所以找了一個下午的bug才發現。如果是用ssm整合shiro也大致一樣,只不過需要在web.xml中新增一些配置資訊。

具體流程大同小異。

@SpringBootApplication(scanBasePackages = "cn.zhq")
@EntityScan("cn.zhq.system.entity")
public class MyBlogApplication {
    public static void main(String[] args) {
        SpringApplication.run(MyBlogApplication.class);
    }
}

3.自定義realm域

個人覺得realm就相當於一個數據源 ,shiro從realm中去獲取一些資料,驗證使用者的認證和授權。

3.1 usermapper介面

@Mapper
public interface UserMapper {

    /**
     * 根據Name查詢使用者資料
     */
    SysUser findByName(String username);
}

3.2 配置檔案usermapper.xml

<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
<mapper namespace="cn.zhq.system.mapper.UserMapper">
    <select id="findByName" resultType="sysuser" parameterType="String">
      select * from tb_user where username = #{username}
    </select>
</mapper>

3.3 編寫自定義realm並繼承AuthorizingRealm

這裡只貼出認證的方法。

    @Autowired
    private UserMapper userMapper;

    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
        //1.獲取登入的使用者名稱密碼(token)
        UsernamePasswordToken upToken = (UsernamePasswordToken) authenticationToken;
        String username = upToken.getUsername();
        String password = new String( upToken.getPassword());
        //2.根據使用者名稱查詢資料庫
        SysUser user = userMapper.findByName(username);
        //3.判斷使用者是否存在或者密碼是否一致
        if(user != null && user.getPassword().equals(password)) {
            //4.如果一致返回安全資料
            //構造方法:安全資料,密碼,realm域名
            SimpleAuthenticationInfo info = new SimpleAuthenticationInfo(user,user.getPassword(),this.getName());
            return info;
        }
        //5.不一致,返回null(丟擲異常)
        return null;
    }    

4.編寫shiro配置類

4.1 安全管理器

    //配置自定義的Realm
    @Bean
    public AuthRealm getRealm() {
        return new AuthRealm();
    }

    //配置安全管理器
    @Bean
    public SecurityManager securityManager(AuthRealm realm) {
        //使用預設的安全管理器
        DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager(realm);
        //將自定義的realm交給安全管理器統一排程管理
        securityManager.setRealm(realm);
        return securityManager;
    }

4.2 配置過濾器工廠

@Bean
    public ShiroFilterFactoryBean shiroFilter(SecurityManager securityManager) {
        //1.建立過濾器工廠
        ShiroFilterFactoryBean filterFactory = new ShiroFilterFactoryBean();
        //2.設定安全管理器
        filterFactory.setSecurityManager(securityManager);
        //3.通用配置(跳轉登入頁面,為授權跳轉的頁面)
        filterFactory.setLoginUrl("#");//跳轉url地址
        filterFactory.setUnauthorizedUrl("#");//未授權的url
        return filterFactory;
    }

5. 編寫controller方法

    @RequestMapping(value="/login")
    @ResponseBody
    public String login(String username,String password) {
        try{
            Subject subject = SecurityUtils.getSubject();
            UsernamePasswordToken uptoken = new UsernamePasswordToken(username,password);
            subject.login(uptoken);
            return "登入成功";
        }catch (Exception e) {
            return "使用者名稱或密碼錯誤";
        }
    }

6.登陸

6.1 獲取md5加密的密碼

由於密碼是使用shiro提供的Md5加密方式。為了避免麻煩就直接列印加密之後的密碼。

Md5Hash的引數代表的含義分別是 加密的內容 | 鹽(加密的混淆字串) | 加密次數
System.out.println(new Md5Hash("123456","zhangbo",3).toString());

可以看到使用加密過的密碼是可以登陸成功的,但使用原始密碼是無法登陸成功的,可以在具體的業務邏輯層中新增使用者時將密碼進行加密處