概要
Spring Securityを使った認証で、裏側でLDAPを使って認証させたいときって具体的にどういうコードを書けばいいんだいっていうお話
今回認証はLDAP、権限の管理はDBで行っている。
具体的な話
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-ldap</artifactId>
<version>3.2.5.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
<version>1.0.2.RELEASE</version>
</dependency>
@Controller
public class LoginController {
@RequestMapping(value = "/login", method = RequestMethod.GET)
public String loginInput() {
return "login";
}
@RequestMapping(value = "/login", method = RequestMethod.POST)
public String login() {
return "search";
}
}
- 権限情報の設定
権限の管理はDBに保存されている情報から取得する。
権限の情報をSpringに渡すにはLdapAuthoritiesPupulatorをimplementsしたクラスを作成する。
@Component
public class DbRoleLdapAuthoritiesPopulator implements LdapAuthoritiesPopulator{
@Autowired
private UserRepository userRepository;
@Override
public Collection<? extends GrantedAuthority> getGrantedAuthorities(DirContextOperations dirContextOperations, String username) {
List<GrantedAuthority> authorities = new ArrayList<>();
User user = userRepository.findByName(username);
for (Authority auth : Authority.values()) {
if (auth.getAuthCode() == user.getAuthority()) {
authorities.add(new SimpleGrantedAuthority(auth.name())); //auth.nameは"ADMIN"とか権限の名前が入る。ROLE_をプレフィックスにするとエラーが出た。
break;
}
}
return authorities;
}
- 認証方法の設定
@Configuration
@EnableWebMvcSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable();
http.authorizeRequests().
antMatchers("/login").permitAll().anyRequest().authenticated().and().
formLogin().loginPage("/login").failureUrl("/login").defaultSuccessUrl("/search").and().
logout().logoutUrl("/logout").permitAll();
}
@Override
public void configure(AuthenticationManagerBuilder auth) throws Exception {
DefaultSpringSecurityContextSource contextSource = new DefaultSpringSecurityContextSource("ldap://${ldap_url}:${ldap_port}");
contextSource.afterPropertiesSet();
LdapAuthenticationProviderConfigurer<AuthenticationManagerBuilder> configure = auth.ldapAuthentication();
configure.userDnPatterns("uid={0},ou=fuga,dc=hoge,dc=co,dc=jp").
contextSource(contextSource).
ldapAuthoritiesPopulator(dbRoleLdapAuthoritiesPopulator);
}
}
protected void configure(HttpSecurity http)
このメソッドは認証には関係ない。
ただantMathcers("path").permitAll()しているURL以外(この場合/login以外)にアクセスした時にログインページへ遷移して認証が求められるようになっている。
public void configure(AuthenticationManagerBuilder auth)
認証設定の本命
メソッド内で呼び出されている"ou=fuga,dc=hoge,dc=co,dc=jp"などの引数は各々の環境でのLDAP設定を書いて貰えばいい。
ただ、uid={0}としているところではまった。
ここにはログインの際に入力したユーザ名が入るのだが、ログインフォームのname属性をusernameにしなければならない。そういえばpasswordもname="password"じゃないとダメな気がしてきた。
- ログインフォーム
<form class="loginForm" action="/login" method="POST" name="loginForm">
<!--nameはusername固定-->
<input name="username" type="text">
<input name="password" type="password">
<input type="submit" value="ログイン">
</form>
LDAPの話と直接関係ないけど、Spring Securityを入れるとデフォルトでオンになるBasic認証は以下の設定を書けばオフにできる
security:
basic:
enabled: false
参考
http://www.slideshare.net/makingx/grails-30-spring-boot
135スライド目からSpring Securityの話