天天看點

shiro實踐(1):注冊使用者密碼加密、登入驗證及權限驗證

shiro是java的安全架構,能友善地實作項目的身份驗證、權限驗證等相關安全方面的功能。本人用的shiro版本是1.2.3的,當然還是推薦高版本的,功能封裝得更完善些。

1.使用者注冊時,将使用者設定的密碼加密後存入資料庫中(顯然密碼不能簡單地用md5加密一次或者幹脆不加密,這些都是會暴露使用者隐私的,甚至是觸動使用者的利益):

1         //生成鹽(部分,需要存入資料庫中)
2         String random=new SecureRandomNumberGenerator().nextBytes().toHex();
3         
4         //将原始密碼加鹽(上面生成的鹽),并且用md5算法加密三次,将最後結果存入資料庫中
5         String result = new Md5Hash("password",random,3).toString();      

2.登入驗證及權限驗證(繼承AuthorizingRealm,覆寫其中的方法):

1 @Component
 2 public class MyRealM extends AuthorizingRealm {
 3 
 4 
 5     @Autowired
 6     private LoginService loginService;
 7 
 8     /**
 9      * 擷取使用者角色和權限,用于權限認證
10      * @param principals
11      * @return
12      */
13     @Override
14     protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
15 
16         String username = principals.getPrimaryPrincipal().toString();
17 
18         SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
19         //擷取角色(從資料庫中取出時使用逗号分隔的)
20         UserInfo user = loginService.getUserByName(username);
21         String[] roleArray = user.getUserrole().split(",");
22 
23         Set<String> roles = new HashSet<String>();
24         for (String roleid : roleArray) {
25             roles.add(loginService.getRoles(roleid));
26         }
27 
28         //擷取權限(根據角色查詢權限表)
29         Set<String> permissions = new HashSet<String>();
30         for (String roleid : roleArray) {
31             permissions.addAll(loginService.getPermissions(roleid));
32         }
33 
34         info.setRoles(roles);
35         info.setStringPermissions(permissions);
36         return info;
37     }
38 
39     /**
40      * 設定使用者登入認證
41      * @param token
42      * @return
43      * @throws AuthenticationException
44      */
45     @Override
46     protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
47         //擷取輸入的使用者賬号,并通過賬号擷取相關資訊
48         String username = token.getPrincipal().toString();
49         UserInfo user = loginService.getUserByName(username);
50         if (user != null) {
51             //将查詢到的使用者賬号和密碼存放到 authenticationInfo用于後面的權限判斷。第三個參數傳入使用者輸入的使用者名。
52             SimpleAuthenticationInfo authenticationInfo = new SimpleAuthenticationInfo(user.getUsername(), user.getPwd(), getName());
53             //設定鹽,用來核對密碼
54             authenticationInfo.setCredentialsSalt(ByteSource.Util.bytes(user.getRandom()));
55           
56             return authenticationInfo;
57         } else {
58             return null;
59         }
60 
61     }
62 
63 
64 }      

3.shiro增加的配置:

1     <!-- 配置自定義Realm,設定核對密碼時在加鹽後,要用MD5算法對使用者輸入的密碼加密3次用于核對 -->
 2     <bean id="myRealM" class="com.test.shiro.MyRealM">
 3         <property name="credentialsMatcher" >
 4             <bean class="org.apache.shiro.authc.credential.HashedCredentialsMatcher">
 5                 <property name="hashAlgorithmName" value="MD5"></property>
 6                 <property name="hashIterations" value="3"></property>
 7             </bean>
 8         </property>
 9     </bean>
10 
11 
12     <!-- 安全管理器 -->
13     <bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">
14         <property name="realm" ref="myRealM"/>
15     </bean>
16 
17     <!--Shiro過濾器-->
18     <bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">
19         <!-- Shiro的核心安全接口,這個屬性是必須的 -->
20         <property name="securityManager" ref="securityManager"/>
21         <!-- 身份認證失敗,則跳轉到登入頁面的配置 -->
22         <property name="loginUrl" value="/sourceA/pageA"/>
23         <!-- 權限認證失敗,則跳轉到指定頁面 -->
24         <property name="unauthorizedUrl" value="/sourceA/error"/>
25         <!-- Shiro連接配接限制配置,即過濾鍊的定義 -->
26         <property name="filterChainDefinitions">
27             <value>
28                  <!--anon 表示匿名通路,不需要認證以及授權 -->
29                 /sourceB=anon
30                  <!--authc表示需要認證,沒有進行身份認證是不能進行通路的-->
31                 /sourceA*=authc
32                  <!--roles[内容] 表示需要内容所示的角色才能通路該路徑-->
33                 /sourceA=roles[user]
34                  <!--perms[内容] 表示需要内容所示的權限才能通路該路徑-->
35                 /sourceC/**=perms["sourceC"]
36                 /sourceD/**=authc,perms["sourceD"]
37            
38             </value>
39         </property>
40     </bean>      

4.登入,調用使用者登入驗證(權限及角色驗證在使用者通路某路徑時進行攔截):

1         //使用者資訊bean      
 2         UserInfo info = new UserInfo();
 3         info.setPwd("password");
 4         info.setUsername("username");
 5 
 6         Subject subject = SecurityUtils.getSubject();
 7         UsernamePasswordToken token = new UsernamePasswordToken(info.getUsername(), info.getPwd());
 8 
 9         try {
10 
11             //驗證
12             subject.login(token);
13            
14             //登陸成功後的處理邏輯:      
15             System.out.println("登陸成功");
16            
17         } catch (Exception e) {
18             //登陸失敗後的處理邏輯:
19             System.out.println("使用者名或密碼錯誤");
20            
21         }      

5.登出

1   Subject subject = SecurityUtils.getSubject();
2         if (subject.isAuthenticated()) {
3             subject.logout();
4         }      

轉載于:https://www.cnblogs.com/dazl/p/8483552.html