1 /*
2  * Licensed to the Apache Software Foundation (ASF) under one
3  * or more contributor license agreements.  See the NOTICE file
4  * distributed with this work for additional information
5  * regarding copyright ownership.  The ASF licenses this file
6  * to you under the Apache License, Version 2.0 (the
7  * "License"); you may not use this file except in compliance
8  * with the License.  You may obtain a copy of the License at
9  *
10  *     http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing,
13  * software distributed under the License is distributed on an
14  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15  * KIND, either express or implied.  See the License for the
16  * specific language governing permissions and limitations
17  * under the License.
18  */
19 module hunt.shiro.authc.pam.AbstractAuthenticationStrategy;
20 
21 import hunt.shiro.authc.pam.AuthenticationStrategy;
22 
23 import hunt.shiro.authc.AuthenticationInfo;
24 import hunt.shiro.authc.AuthenticationToken;
25 import hunt.shiro.authc.MergableAuthenticationInfo;
26 import hunt.shiro.authc.SimpleAuthenticationInfo;
27 
28 // import hunt.shiro.authc;
29 import hunt.shiro.realm.Realm;
30 
31 import hunt.Exceptions;
32 import hunt.collection;
33 
34 
35 /**
36  * Abstract base implementation for Shiro's concrete <code>AuthenticationStrategy</code>
37  * implementations.
38  *
39  */
40 abstract class AbstractAuthenticationStrategy : AuthenticationStrategy {
41 
42     /**
43      * Simply returns <code>new {@link hunt.shiro.authc.SimpleAuthenticationInfo SimpleAuthenticationInfo}();</code>, which supports
44      * aggregating account data across realms.
45      */
46      AuthenticationInfo beforeAllAttempts(Realm[] realms, AuthenticationToken token){
47         return new SimpleAuthenticationInfo();
48     }
49 
50     /**
51      * Simply returns the <code>aggregate</code> method argument, without modification.
52      */
53      AuthenticationInfo beforeAttempt(Realm realm, AuthenticationToken token, AuthenticationInfo aggregate){
54         return aggregate;
55     }
56 
57     /**
58      * Base implementation that will aggregate the specified <code>singleRealmInfo</code> into the
59      * <code>aggregateInfo</code> and then returns the aggregate.  Can be overridden by subclasses for custom behavior.
60      */
61      AuthenticationInfo afterAttempt(Realm realm, AuthenticationToken token, 
62                 AuthenticationInfo singleRealmInfo, AuthenticationInfo aggregateInfo, Throwable t){
63                     
64         AuthenticationInfo info;
65         if (singleRealmInfo  is null) {
66             info = aggregateInfo;
67         } else {
68             if (aggregateInfo  is null) {
69                 info = singleRealmInfo;
70             } else {
71                 info = merge(singleRealmInfo, aggregateInfo);
72             }
73         }
74 
75         return info;
76     }
77 
78     /**
79      * Merges the specified <code>info</code> argument into the <code>aggregate</code> argument and then returns an
80      * aggregate for continued use throughout the login process.
81      * <p/>
82      * This implementation merely checks to see if the specified <code>aggregate</code> argument is an instance of
83      * {@link hunt.shiro.authc.MergableAuthenticationInfo MergableAuthenticationInfo}, and if so, calls
84      * <code>aggregate.merge(info)</code>  If it is <em>not</em> an instance of
85      * <code>MergableAuthenticationInfo</code>, an {@link IllegalArgumentException IllegalArgumentException} is thrown.
86      * Can be overridden by subclasses for custom merging behavior if implementing the
87      * {@link hunt.shiro.authc.MergableAuthenticationInfo MergableAuthenticationInfo} is not desired for some reason.
88      */
89     protected AuthenticationInfo merge(AuthenticationInfo info, AuthenticationInfo aggregate) {
90         auto aggregateCast = cast(MergableAuthenticationInfo)aggregate;
91         if( aggregateCast !is null ) {
92             aggregateCast.merge(info);
93             return aggregate;
94         } else {
95             throw new IllegalArgumentException( "Attempt to merge authentication info " ~ 
96                         "from multiple realms, but aggregate " ~
97                         "AuthenticationInfo is not of type MergableAuthenticationInfo." );
98         }
99     }
100 
101     /**
102      * Simply returns the <code>aggregate</code> argument without modification.  Can be overridden for custom behavior.
103      */
104      AuthenticationInfo afterAllAttempts(AuthenticationToken token, AuthenticationInfo aggregate){
105         return aggregate;
106     }
107 }