File D:\maven-qcr-plugin-testsunitaires\qcr4java\jenkins-master\target\site\qc\core\src\main\java\hudson\security\AbstractPasswordBasedSecurityRealm.java.html

1 package hudson.security;
2
3 import groovy.lang.Binding;
4 import hudson.FilePath;
5 import hudson.cli.CLICommand;
6 import jenkins.model.Jenkins;
7 import hudson.remoting.Callable;
8 import hudson.util.spring.BeanBuilder;
9 import org.acegisecurity.Authentication;
10 import org.acegisecurity.AuthenticationException;
11 import org.acegisecurity.AuthenticationManager;
12 import org.acegisecurity.BadCredentialsException;
13 import org.acegisecurity.providers.UsernamePasswordAuthenticationToken;
14 import org.acegisecurity.providers.dao.AbstractUserDetailsAuthenticationProvider;
15 import org.acegisecurity.userdetails.UserDetails;
16 import org.acegisecurity.userdetails.UserDetailsService;
17 import org.acegisecurity.userdetails.UsernameNotFoundException;
18 import org.codehaus.mojo.animal_sniffer.IgnoreJRERequirement;
19 import org.kohsuke.args4j.Option;
20 import org.springframework.dao.DataAccessException;
21 import org.springframework.web.context.WebApplicationContext;
22
23 import java.io.Console;
24 import java.io.IOException;
25
26 /**
27 * Partial implementation of {@link SecurityRealm} for username/password based authentication.
28 * This is a convenience base class if all you are trying to do is to check the given username
29 * and password with the information stored in somewhere else, and you don't want to do anything
30 * with Acegi.
31 *
32 * <p>
33 * This {@link SecurityRealm} uses the standard login form (and a few other optional mechanisms like BASIC auth)
34 * to gather the username/password information. Subtypes are responsible for authenticating this information.
35 *
36 * @author Kohsuke Kawaguchi
37 * @since 1.317
38 */
39 public abstract class AbstractPasswordBasedSecurityRealm extends SecurityRealm implements UserDetailsService {
40 @Override
41 public SecurityComponents createSecurityComponents() {
42 Binding binding = new Binding();
43 binding.setVariable("authenticator", new Authenticator());
44
45 BeanBuilder builder = new BeanBuilder();
46 builder.parse(Jenkins.getInstance().servletContext.getResourceAsStream("/WEB-INF/security/AbstractPasswordBasedSecurityRealm.groovy"),binding);
47 WebApplicationContext context = builder.createApplicationContext();
48 return new SecurityComponents(
49 findBean(AuthenticationManager.class, context),this);
50 }
51
52 @Override
53 public CliAuthenticator createCliAuthenticator(final CLICommand command) {
54 return new CliAuthenticator() {
55 @Option(name="--username",usage="User name to authenticate yourself to Jenkins")
56 public String userName;
57
58 @Option(name="--password",usage="Password for authentication. Note that passing a password in arguments is insecure.")
59 public String password;
60
61 @Option(name="--password-file",usage="File that contains the password")
62 public String passwordFile;
63
64 public Authentication authenticate() throws AuthenticationException, IOException, InterruptedException {
65 if (userName==null)
66 return command.getTransportAuthentication(); // no authentication parameter. fallback to the transport
67
68 if (passwordFile!=null)
69 try {
70 password = new FilePath(command.channel,passwordFile).readToString().trim();
71 } catch (IOException e) {
72 throw new BadCredentialsException("Failed to read "+passwordFile,e);
73 }
74 if (password==null)
75 password = command.channel.call(new InteractivelyAskForPassword());
76
77 if (password==null)
78 throw new BadCredentialsException("No password specified");
79
80 UserDetails d = AbstractPasswordBasedSecurityRealm.this.authenticate(userName, password);
81 return new UsernamePasswordAuthenticationToken(d, password, d.getAuthorities());
82 }
83 };
84 }
85
86 /**
87 * Authenticate a login attempt.
88 * This method is the heart of a {@link AbstractPasswordBasedSecurityRealm}.
89 *
90 * <p>
91 * If the user name and the password pair matches, retrieve the information about this user and
92 * return it as a {@link UserDetails} object. {@link org.acegisecurity.userdetails.User} is a convenient
93 * implementation to use, but if your backend offers additional data, you may want to use your own subtype
94 * so that the rest of Hudson can use those additional information (such as e-mail address --- see
95 * MailAddressResolver.)
96 *
97 * <p>
98 * Properties like {@link UserDetails#getPassword()} make no sense, so just return an empty value from it.
99 * The only information that you need to pay real attention is {@link UserDetails#getAuthorities()}, which
100 * is a list of roles/groups that the user is in. At minimum, this must contain {@link #AUTHENTICATED_AUTHORITY}
101 * (which indicates that this user is authenticated and not anonymous), but if your backend supports a notion
102 * of groups, you should make sure that the authorities contain one entry per one group. This enables
103 * users to control authorization based on groups.
104 *
105 * <p>
106 * If the user name and the password pair doesn't match, throw {@link AuthenticationException} to reject the login
107 * attempt.
108 */
109 protected abstract UserDetails authenticate(String username, String password) throws AuthenticationException;
110
111 /**
112 * Retrieves information about an user by its name.
113 *
114 * <p>
115 * This method is used, for example, to validate if the given token is a valid user name when the user is configuring an ACL.
116 * This is an optional method that improves the user experience. If your backend doesn't support
117 * a query like this, just always throw {@link UsernameNotFoundException}.
118 */
119 @Override
120 public abstract UserDetails loadUserByUsername(String username) throws UsernameNotFoundException, DataAccessException;
121
122 /**
123 * Retrieves information about a group by its name.
124 *
125 * This method is the group version of the {@link #loadUserByUsername(String)}.
126 */
127 @Override
128 public abstract GroupDetails loadGroupByGroupname(String groupname) throws UsernameNotFoundException, DataAccessException;
129
130 class Authenticator extends AbstractUserDetailsAuthenticationProvider {
131 protected void additionalAuthenticationChecks(UserDetails userDetails, UsernamePasswordAuthenticationToken authentication) throws AuthenticationException {
132 // authentication is assumed to be done already in the retrieveUser method
133 }
134
135 protected UserDetails retrieveUser(String username, UsernamePasswordAuthenticationToken authentication) throws AuthenticationException {
136 return AbstractPasswordBasedSecurityRealm.this.authenticate(username,authentication.getCredentials().toString());
137 }
138 }
139
140 /**
141 * Asks for the password.
142 */
143 private static class InteractivelyAskForPassword implements Callable<String,IOException> {
144 @IgnoreJRERequirement
145 public String call() throws IOException {
146 Console console = System.console();
147 if (console == null) return null; // no terminal
148
149 char[] w = console.readPassword("Password:");
150 if (w==null) return null;
151 return new String(w);
152 }
153
154 private static final long serialVersionUID = 1L;
155 }
156 }
157