Tomcat JAAS 身份验证和授权

来源:互联网 发布:paparecipe正品软件 编辑:程序博客网 时间:2024/05/17 05:06

ava 认证和授权服务(JAAS)是一种用于验证用户身份以确定安全等级的 Tomcat Realm ( org.apache.catalina.Realm)的实现。

需求

Tomcat 7.0, MVC (推荐 Spring MVC)和数据库(推荐 Mysql)

1. 配置

appName

appName 属性的值将被传递给 LoginContext (javax.security.auth.login.LoginContext) 构造函数,以指定实现LoginModule ( javax.security.auth.spi.LoginModule) 的实体名称。

LoginModule 是一个提供了特定类型的身份验证的可插拔接口。 LoginContext 通过读取配置(javax.security.auth.login.Configuration) 指定登录程序中的登录模块(S)。

K6F
K6F
翻译于 3年前

0人顶

 翻译的不错哦!

一个登录配置包括以下信息 :

?
1
2
3
4
5
Name {
       ModuleClass  Flag    ModuleOptions;
       ModuleClass  Flag    ModuleOptions;
       ModuleClass  Flag    ModuleOptions;
 };

一个登录配置中可能包括不只一个的登录模块。

ModuleClass 是登录模块的完整相称类名。Flag 值 ( Required, Requisite, Sufficient, Optional ) 则控制身份验证的行为。

ModuleOptions则直接将值传递给底层登录模块,它的格式是一个用空格分割的列表。

将下列 Tomcat JAAS Realm 配置添加到 Tomcat server.xml 文件中:

?
1
2
3
<realmclassname="org.apache.catalina.realm.JAASRealm"appname="jasslogin"userclassnames="com.test.secure.TestUserPrincipal"roleclassnames="com.test.secure.TestRolePrincipal">
  
</realm>

在 tomcat/conf 文件夹中创建 jass.config 文件:

?
1
2
3
jasslogin{
com.test.secure.TestLoginModule  required;
};

在 tomcat/bin 文件夹中创建 setenv.bat 文件,并添加下列配置:

?
1
set JAVA_OPTS=-Djava.security.auth.login.config==C:/tomcat/conf/jaas.config
K6F
K6F
翻译于 3年前

0人顶

 翻译的不错哦!

其它翻译版本(1)

2. 登录模块

当 logincontext 读取配置时,登录模块将初始化,包括 Subject ( javax.security.auth.Subject),回叫处理(javax.security.auth.callback.CallBackHandler),共享登录模块以及 LoginModule-specific 选项。

?
1
booleanlogin() throwsLoginException;

第一个被 LoginContext 调用来实际处理身份验证的方法是 Login 方法,它将返回 true 或 false 。如果验证成功,commit 方法将被调用。

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
packagecom.test.secure;
 
importjava.io.IOException;
importjava.security.Principal;
importjava.sql.Connection;
importjava.sql.DriverManager;
importjava.sql.PreparedStatement;
importjava.sql.ResultSet;
importjava.sql.SQLException;
importjava.util.ArrayList;
importjava.util.List;
importjava.util.Map;
 
importjavax.security.auth.Subject;
importjavax.security.auth.callback.Callback;
importjavax.security.auth.callback.CallbackHandler;
importjavax.security.auth.callback.NameCallback;
importjavax.security.auth.callback.PasswordCallback;
importjavax.security.auth.callback.UnsupportedCallbackException;
importjavax.security.auth.login.LoginException;
importjavax.security.auth.spi.LoginModule;
 
importorg.apache.log4j.Logger;
 
publicclass TestLoginModule implementsLoginModule {
 
    Logger logger = Logger.getLogger(TestLoginModule.class);
    publicstatic String USER_QUERY = "select user_name from users where user_name=? and user_pass=?";
    publicstatic String ROLE_QUERY = "select role_name from  user_roles where user_name=?";
 
    privateSubject subject;
    privateCallbackHandler callbackHandler;
    privateMap sharedState;
    privateMap options;
 
    // configurable option
    privateboolean debug = false;
 
    // the authentication status
    privateboolean succeeded = false;
    privateboolean commitSucceeded = false;
 
    // user credentials
    privateString username = null;
    privatechar[] password = null;
    // principals
    privateTestUserPrincipal testUserPrincipal;
    privateTestRolePrincipal testRolePrincipal;
    privateTestPasswordPrincipal testPasswordPrincipal;
 
    @Override
    publicvoid initialize(Subject subject, CallbackHandler callbackHandler,
            Map<String, ?> sharedState, Map<String, ?> options) {
 
        this.subject = subject;
        this.callbackHandler = callbackHandler;
        this.sharedState = sharedState;
        this.options = options;
 
    }
 
    @Override
    publicboolean login() throwsLoginException {
 
        if(callbackHandler == null) {
            thrownew LoginException("call back handler is null");
        }
 
        Callback[] callbacks = newCallback[2];
        callbacks[0] = newNameCallback("username");
        callbacks[1] = newPasswordCallback("password: "false);
 
        try{
 
            callbackHandler.handle(callbacks);
             
            username = ((NameCallback) callbacks[0]).getName();
            password = ((PasswordCallback) callbacks[1]).getPassword();
 
            if(username == null|| password == null) {
                thrownew LoginException(
                        "Callback handler does not return login data properly");
 
            }
 
            logger.info(" username" + username);
            logger.info("password"+ password);
 
            // authenticate
 
            if(isValidUser()) {
                succeeded = true;
                returntrue;
            }
             
         
 
        catch(IOException e) {
            e.printStackTrace();
        catch(UnsupportedCallbackException e) {
            e.printStackTrace();
        }
 
        returnfalse;
    }
 
    @Override
    publicboolean commit() throwsLoginException {
         
        logger.info("committing...");
 
        if(succeeded == false) {
            returnfalse;
        else{
            testUserPrincipal = newTestUserPrincipal(username);
             
             
            if(!subject.getPrincipals().contains(testUserPrincipal)) {
                subject.getPrincipals().add(testUserPrincipal);
                 
            }
             
             
        /*  testPasswordPrincipal = new TestPasswordPrincipal(new String(
                    password));
            if (!subject.getPrincipals().contains(testPasswordPrincipal)) {
                subject.getPrincipals().add(testPasswordPrincipal);
                 
            }
*/
            // populate subject with roles.
             
             
            // strings
            List roles = getRoles(testUserPrincipal);
             
             
             
            for(String role : roles) {
                 
                 
                 
                testRolePrincipal = newTestRolePrincipal(role);
                 
                if(!subject.getPrincipals().contains(testRolePrincipal)) {
                     
                    subject.getPrincipals().add(testRolePrincipal);
                     
                }
                     
                     
                 
            }
             
             
            commitSucceeded = true;
 
            logger.info("Login subject were successfully populated with principals and roles");
            logger.info("--------------principals");
            logger.info(subject.getPrincipals());
                 
            
             
            for(Principal p: subject.getPrincipals()){
                 
                if(p instanceofTestRolePrincipal){
                     
                    logger.info(" ROLE: "+p.getName());
                     
                }
                 
                 
            }
             
             
             
 
            returntrue;
        }
    }
 
    @Override
    publicboolean abort() throwsLoginException {
 
        if(succeeded == false) {
            returnfalse;
        elseif (succeeded == true&& commitSucceeded == false) {
            succeeded = false;
            username = null;
            if(password != null) {
                password = null;
            }
            testUserPrincipal = null;
        else{
            logout();
        }
        returntrue;
    }
 
    @Override
    publicboolean logout() throwsLoginException {
 
        subject.getPrincipals().remove(testUserPrincipal);
        succeeded = false;
        succeeded = commitSucceeded;
        username = null;
        if(password != null) {
            for(inti = 0; i < password.length; i++) {
                password[i] = ' ';
                password = null;
            }
        }
        testUserPrincipal = null;
        returntrue;
    }
 
    privateboolean isValidUser() throwsLoginException {
 
        Connection connection = null;
 
        ResultSet rs = null;
        PreparedStatement stmt = null;
 
        try{
 
            connection = getConnection();
 
            stmt = connection.prepareStatement(USER_QUERY);
            stmt.setString(1, username);
            stmt.setString(2newString(password));
 
            rs = stmt.executeQuery();
 
            if(rs.next()) { // User exist with the given user name and
                                // password.
                returntrue;
            }
        catch(Exception e) {
            logger.error("Error when loading user from the database " + e);
            e.printStackTrace();
        finally{
            try{
                rs.close();
            catch(SQLException e) {
                logger.error("Error when closing result set." + e);
            }
            try{
                stmt.close();
            catch(SQLException e) {
                logger.error("Error when closing statement." + e);
            }
            try{
                connection.close();
            catch(SQLException e) {
                logger.error("Error when closing connection." + e);
            }
        }
        returnfalse;
    }
 
    privateList getRoles(TestUserPrincipal user) {
 
        Connection connection = null;
 
        ResultSet rs = null;
        PreparedStatement stmt = null;
 
        List roleList = newArrayList();
 
        try{
 
            connection = getConnection();
 
            stmt = connection.prepareStatement(ROLE_QUERY);
            stmt.setString(1, username);
 
            rs = stmt.executeQuery();
 
            while(rs.next()) {
                roleList.add(rs.getString("role_name"));
                user.addRole(newTestRolePrincipal((rs.getString("role_name"))));
            }
        catch(Exception e) {
            logger.error("Error when loading user from the database " + e);
            e.printStackTrace();
        finally{
            try{
                rs.close();
            catch(SQLException e) {
                logger.error("Error when closing result set." + e);
            }
            try{
                stmt.close();
            catch(SQLException e) {
                logger.error("Error when closing statement." + e);
            }
            try{
                connection.close();
            catch(SQLException e) {
                logger.error("Error when closing connection." + e);
            }
        }
         
        returnroleList;
    }
 
    privateConnection getConnection() {
 
        try{
            Class.forName("com.mysql.jdbc.Driver");
            returnDriverManager.getConnection(
                    "jdbc:mysql://localhost:3306/test""root""password");
        catch(Exception e) {
            e.printStackTrace();
        }
        returnnull;
    }
 
}
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
packagecom.test.secure;
 
importjava.security.Principal;
importjava.util.HashSet;
importjava.util.Iterator;
importjava.util.Set;
 
importorg.apache.catalina.Group;
importorg.apache.catalina.Role;
importorg.apache.catalina.User;
importorg.apache.catalina.UserDatabase;
 
publicclass TestUserPrincipal implementsUser {
     
     
    privateString username;
    privateSet roles = newHashSet();
     
    publicTestUserPrincipal(String u){
        this.username=u;
    }
 
    @Override
    publicString getName() {
        // TODO Auto-generated method stub
        return username;
    }
 
    @Override
    publicvoid addGroup(Group arg0) {
        // TODO Auto-generated method stub
         
    }
 
    @Override
    publicvoid addRole(Role role) {
    roles.add(role);
         
    }
 
    @Override
    publicString getFullName() {
        // TODO Auto-generated method stub
        returnusername;
    }
 
    @Override
    publicIterator getGroups() {
         
         
         
        returnnull;
    }
 
    @Override
    publicString getPassword() {
        // TODO Auto-generated method stub
        returnnull;
    }
 
    @Override
    publicIterator getRoles() {
 
        returnroles.iterator();
    }
 
    @Override
    publicUserDatabase getUserDatabase() {
        // TODO Auto-generated method stub
        returnnull;
    }
 
    @Override
    publicString getUsername() {
        // TODO Auto-generated method stub
        returnusername;
    }
 
    @Override
    publicboolean isInGroup(Group arg0) {
        // TODO Auto-generated method stub
        returnfalse;
    }
 
    @Override
    publicboolean isInRole(Role role) {
         
        if(1==1){
            returntrue;
        }
         
        if(!roles.isEmpty()){
            Iterator it =roles.iterator();
            while(it.hasNext()){
            Role rol =(Role)it.next();
            if(rol.getName()!=null&& rol.getName().equals(role.getName())){
                returntrue;
            }
            }
        }
         
        returnfalse;
    }
 
    @Override
    publicvoid removeGroup(Group arg0) {
        // TODO Auto-generated method stub
         
    }
 
    @Override
    publicvoid removeGroups() {
        // TODO Auto-generated method stub
         
    }
 
    @Override
    publicvoid removeRole(Role arg0) {
        // TODO Auto-generated method stub
         
    }
 
    @Override
    publicvoid removeRoles() {
        roles.clear();
         
    }
 
    @Override
    publicvoid setFullName(String arg0) {
        setUsername(username);
         
    }
 
    @Override
    publicvoid setPassword(String arg0) {
        // TODO Auto-generated method stub
         
    }
 
    @Override
    publicvoid setUsername(String arg0) {
     this.username=arg0;
         
    }
 
     
     
}
 
 
packagecom.test.secure;
 
importjava.io.Serializable;
 
importjava.security.Principal;
 
importorg.apache.catalina.Role;
importorg.apache.catalina.UserDatabase;
 
publicclass TestRolePrincipal implementsRole, Serializable {
     
     
    privateString roleName;
     
     
    publicTestRolePrincipal(String name){
        this.roleName=name;
    }
 
    @Override
    publicString getName() {
        // TODO Auto-generated method stub
        returngetRolename();
    }
 
    @Override
    publicString getDescription() {
        // TODO Auto-generated method stub
        return" some role";
    }
 
    @Override
    publicString getRolename() {
        // TODO Auto-generated method stub
        returnroleName;
    }
 
    @Override
    publicUserDatabase getUserDatabase() {
        // TODO Auto-generated method stub
        returnnull;
    }
 
    @Override
    publicvoid setDescription(String arg0) {
         
         
    }
 
    @Override
    publicvoid setRolename(String arg0) {
        roleName =arg0;
         
    }
 
 
    

你需要将 tomcat/lib 中的三个类都封装到 jar 中,一边在启动时加载。

K6F
K6F
翻译于 3年前

0人顶

 翻译的不错哦!

登录处理器

在这个例子中我们使用的是 Spring MVC,但作为测试,你可使用任何其他的请求处理器,或者只是一个 Servlet:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
packagecom.test.secure;
 
importjava.security.Principal;
 
importjavax.servlet.http.HttpServletRequest;
importjavax.servlet.http.HttpServletResponse;
importjavax.servlet.http.HttpSession;
 
importorg.apache.catalina.Session;
importorg.springframework.web.servlet.ModelAndView;
importorg.springframework.web.servlet.mvc.AbstractController;
 
publicclass SecureController extendsAbstractController {
 
    @Override
    protectedModelAndView handleRequestInternal(HttpServletRequest req,
            HttpServletResponse res) throwsException {
 
  
         
    
         
    ModelAndView m = newModelAndView("SecureView");
    returnm;
    }
 
}

5. 安全约束

在 web.xml 中增加一个安全约束 ( org.apache.catalina.deploy. SecurityConstraint) 和角色授权的资源访问:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
security-constraint>
  
 web-resource-collection>
 web-resource-name>interdit< /web-resource-name>
 url-pattern>/go/*< /url-pattern>
 < /web-resource-collection>
  
 auth-constraint>
 description>tomcat< /description>
 role-name>tomcat< /role-name>
 < /auth-constraint>
 
< /security-constraint>

然后添加登录和登录错误页

?
1
FORMjasslogin/join.do/joinerror.do

红薯
红薯
翻译于 3年前

0人顶

 翻译的不错哦!

6. 用户密码和角色
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
CREATETABLE `users` (
  `user_name` varchar(15) NOTNULL,
  `user_pass` varchar(15) NOTNULL,
  PRIMARYKEY (`user_name`);
 
INSERTINTO `users` VALUES('admin','root'),('role1','root'),('tomcat','tomcat');
 
 
CREATETABLE `user_roles` (
  `user_name` varchar(15) NOTNULL,
  `role_name` varchar(15) NOTNULL,
  PRIMARYKEY (`user_name`,`role_name`);
 
 
INSERTINTO `user_roles` VALUES('tomcat','manager-gui'),('tomcat','manager-jmx'),('tomcat','manager-script'),('tomcat','manager-status'),('tomcat','tomcat');

登录表单

?
1
2
3
4
5
6
7
8
9
10
<formaction="<%= response.encodeURL(" j_security_check")="" %="">" method="post">
  
    <fieldset>
        <legend>Login </legend>
        <p><labelfor="name">Username</label> <inputname="j_username"type="text"></p>
        <p><labelfor="e-mail">Password</label> <inputname="j_password"type="password"><br></p>
        <pclass="submit"><inputvalue="Submit"type="submit"></p>
    </fieldset>
  
</form>
0 0
原创粉丝点击