Created
March 20, 2015 05:53
-
-
Save yusuke2255/a277b49e1e0af2953848 to your computer and use it in GitHub Desktop.
【メモ】DropwizardでCookieのsession idで認証してみる ref: http://qiita.com/Kawata/items/2e8453ac149e365f762a
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
plugins { | |
id 'java' | |
id 'com.github.johnrengelman.shadow' version '1.2.0' | |
} | |
apply plugin: 'java' | |
apply plugin: 'maven' | |
apply plugin: 'application' | |
defaultTasks 'shadowJar' | |
project.ext { | |
authorName = 'Hogeo HOGETA' | |
dropwizardVersion = '0.8.0' | |
} | |
sourceCompatibility = 1.8 | |
targetCompatibility = 1.8 | |
group = 'jp.hoge.app' | |
version = '0.1' | |
applicationName = 'hoge-session-auth' | |
mainClassName = 'jp.hoge.app.HogeApplication' | |
repositories { | |
mavenLocal() | |
mavenCentral() | |
} | |
def defaultEncoding = 'UTF-8' | |
tasks.withType(AbstractCompile)*.options*.encoding = defaultEncoding | |
tasks.withType(GroovyCompile)*.groovyOptions*.encoding = defaultEncoding | |
dependencies { | |
// 全部は要らないけど消すのめんどいんで | |
compile "io.dropwizard:dropwizard-core:${dropwizardVersion}" | |
compile "io.dropwizard:dropwizard-assets:${dropwizardVersion}" | |
compile "io.dropwizard:dropwizard-views:${dropwizardVersion}" | |
compile "io.dropwizard:dropwizard-views-freemarker:${dropwizardVersion}" | |
compile "io.dropwizard:dropwizard-migrations:${dropwizardVersion}" | |
compile "io.dropwizard:dropwizard-hibernate:${dropwizardVersion}" | |
compile "io.dropwizard:dropwizard-jdbi:${dropwizardVersion}" | |
compile "io.dropwizard:dropwizard-auth:${dropwizardVersion}" | |
testCompile "junit:junit:4.11" | |
compile "io.dropwizard:dropwizard-testing:${dropwizardVersion}" | |
} | |
task wrapper(type: Wrapper) { | |
gradleVersion = '2.2' | |
} | |
shadowJar { | |
archiveName = String.format("%s-%s.jar", applicationName, version) | |
mergeServiceFiles() | |
exclude 'META-INF/*.SF' | |
exclude 'META-INF/*.DSA' | |
exclude 'META-INF/*.RSA' | |
} | |
jar { | |
manifest { | |
attributes( | |
'Implementation-Title': applicationName, | |
'Implementation-Version': version, | |
'Built-By': authorName, | |
'Built-Time': new Date(), | |
'Main-Class': mainClassName, | |
'Class-Path': configurations.compile.collect { it.getName() }.join(' ') | |
) | |
} | |
} | |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* TODO コードとか作りとか色々汚いので使うときにはちゃんと修正する */ |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# the key needs to match the suffix of the renderer | |
viewRendererConfiguration: | |
.ftl: | |
strict_syntax: yes | |
whitespace_stripping: yes | |
server: | |
applicationConnectors: | |
- type: http | |
port: 8082 | |
- type: https | |
port: 8443 | |
validateCerts: false | |
adminConnectors: | |
- type: http | |
port: 8084 | |
- type: https | |
port: 8444 | |
validateCerts: false |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package jp.hoge.app.auth; | |
import com.google.common.base.Optional; | |
import jp.hoge.app.core.HogeUser; | |
import io.dropwizard.auth.AuthenticationException; | |
import io.dropwizard.auth.Authenticator; | |
public class HogeSessionAuthenticator implements Authenticator<HogeTokenCredentials, HogeUser> { | |
@Override | |
public Optional<HogeUser> authenticate(HogeTokenCredentials credentials) | |
throws AuthenticationException { | |
// 本来はredisとかに問い合わせて有効か確認してユーザ情報を取得する | |
if ("abcdefg".equals(credentials.getToken())) { | |
return Optional.of(new HogeUser("myID")); | |
} | |
return Optional.absent(); | |
} | |
} | |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package jp.hoge.app.auth; | |
public class HogeTokenCredentials { | |
private final String token; | |
public HogeTokenCredentials(String token) { | |
this.token = token; | |
} | |
public String getToken() { | |
return token; | |
} | |
} | |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package jp.hoge.app.auth; | |
import java.util.Arrays; | |
import java.util.Optional; | |
import javax.servlet.http.HttpServletRequest; | |
import javax.ws.rs.WebApplicationException; | |
import javax.ws.rs.core.Context; | |
import io.dropwizard.auth.AuthFactory; | |
import io.dropwizard.auth.AuthenticationException; | |
import io.dropwizard.auth.Authenticator; | |
import io.dropwizard.auth.UnauthorizedHandler; | |
/** | |
* ほぼほぼio.dropwizard.auth.basic.BasicAuthFactoryの写経でいけた | |
*/ | |
public class SessionUserAuthFactory<T> extends | |
AuthFactory<HogeTokenCredentials, T> { | |
@Context | |
private HttpServletRequest request; | |
private final boolean required; | |
private UnauthorizedHandler unauthorizedHandler = new HogeUnauthorizedHandler(); | |
private final Class<T> generatedClass; | |
private String prefix = "Sid"; // 使わないけど | |
private final String realm; // 使わないけど | |
public SessionUserAuthFactory( | |
Authenticator<HogeTokenCredentials, T> authenticator, | |
final String realm, | |
final Class<T> generatedClass) { | |
super(authenticator); | |
this.required = false; | |
this.realm = realm; | |
this.generatedClass = generatedClass; | |
} | |
private SessionUserAuthFactory(final boolean required, | |
final Authenticator<HogeTokenCredentials, T> authenticator, | |
final String realm, | |
final Class<T> generatedClass) { | |
super(authenticator); | |
this.required = required; | |
this.realm = realm; | |
this.generatedClass = generatedClass; | |
} | |
public SessionUserAuthFactory<T> responseBuilder(UnauthorizedHandler unauthorizedHandler) { | |
this.unauthorizedHandler = unauthorizedHandler; | |
return this; | |
} | |
@Override | |
public T provide() { | |
// ラムダ式で書いてみたかったの (正しいのか知らん) | |
Optional<HogeTokenCredentials> credentials = Optional.ofNullable(request) | |
.map(req -> req.getCookies()) | |
.map(cookies -> Arrays.asList(cookies).stream() | |
.filter(cookie -> "sid".equals(cookie.getName())) | |
.findFirst().orElseGet(null)) | |
.map(sidcookie -> sidcookie.getValue()) | |
.map(sid -> new HogeTokenCredentials(sid)); | |
if (credentials.isPresent()) { | |
try { | |
// guava出てきてもうた | |
final com.google.common.base.Optional<T> result = authenticator().authenticate(credentials.get()); | |
if (result.isPresent()) return result.get(); | |
} catch (AuthenticationException e) { | |
// TODO Auto-generated catch block | |
e.printStackTrace(); | |
} | |
} | |
// 認証必須のリソースの場合はUnauthorizedHandlerを利用してログイン画面に飛ばす | |
if (required) { | |
throw new WebApplicationException(unauthorizedHandler.buildResponse(prefix, realm)); | |
} | |
return null; | |
} | |
@Override | |
public void setRequest(HttpServletRequest request) { | |
this.request = request; | |
} | |
@Override | |
public AuthFactory<HogeTokenCredentials, T> clone(boolean required) { | |
return new SessionUserAuthFactory<>(required, authenticator(),this.realm, this.generatedClass).responseBuilder(unauthorizedHandler); | |
} | |
@Override | |
public Class<T> getGeneratedClass() { | |
return generatedClass; | |
} | |
} | |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package jp.hoge.app.core; | |
public class HogeUser { | |
private final String userId; | |
public HogeUser(String userId) { | |
this.userId = userId; | |
} | |
public String getUserId() { | |
return userId; | |
} | |
} | |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package jp.hoge.app; | |
import jp.hoge.app.auth.HogeSessionAuthenticator; | |
import jp.hoge.app.auth.SessionUserAuthFactory; | |
import jp.hoge.app.core.HogeUser; | |
import jp.hoge.app.resources.LoginResource; | |
import jp.hoge.app.resources.HogeUserResource; | |
import com.google.common.collect.ImmutableMap; | |
import io.dropwizard.Application; | |
import io.dropwizard.auth.AuthFactory; | |
import io.dropwizard.setup.Bootstrap; | |
import io.dropwizard.setup.Environment; | |
import io.dropwizard.views.ViewBundle; | |
public class HogeApplication extends Application<HogeConfiguration> { | |
public static void main(String[] args) throws Exception { | |
new HogeApplication().run(args); | |
} | |
@Override | |
public String getName() { | |
return "hoge-session-auth"; | |
} | |
@Override | |
public void initialize(Bootstrap<HogeConfiguration> bootstrap) { | |
bootstrap.addBundle(new ViewBundle<HogeConfiguration>() { | |
@Override | |
public ImmutableMap<String, ImmutableMap<String, String>> getViewConfiguration(HogeConfiguration config) { | |
return config.getViewRendererConfiguration(); | |
} | |
}); | |
{ | |
} | |
@Override | |
public void run(HogeConfiguration configuration,Environment environment) throws Exception { | |
environment.jersey().register(AuthFactory.binder(new SessionUserAuthFactory<HogeUser>(new HogeSessionAuthenticator(), "HOGE USER", HogeUser.class))); | |
final LoginResource loginResource = new LoginResource(); | |
environment.jersey().register(loginResource); | |
final HogeUserResource hogeUserResource = new HogeUserResource(); | |
environment.jersey().register(hogeUserResource); | |
} | |
} | |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package jp.hoge.app; | |
import javax.validation.constraints.NotNull; | |
import com.fasterxml.jackson.annotation.JsonProperty; | |
import com.google.common.collect.ImmutableMap; | |
import io.dropwizard.Configuration; | |
public class HogeConfiguration extends Configuration { | |
@NotNull | |
private ImmutableMap<String, ImmutableMap<String, String>> viewRendererConfiguration = ImmutableMap.of(); | |
@JsonProperty("viewRendererConfiguration") | |
public ImmutableMap<String, ImmutableMap<String, String>> getViewRendererConfiguration() { | |
return viewRendererConfiguration; | |
} | |
} | |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package jp.hoge.app.resources; | |
import io.dropwizard.auth.Auth; | |
import javax.ws.rs.GET; | |
import javax.ws.rs.Path; | |
import javax.ws.rs.Produces; | |
import javax.ws.rs.core.MediaType; | |
import jp.hoge.app.core.HogeUser; | |
import jp.hoge.app.views.MypageTopView; | |
@Path("/mypage") | |
public class HogeUserResource { | |
@GET | |
@Path("/") | |
@Produces(MediaType.TEXT_HTML) | |
public MypageTopView getMypageView(@Auth HogeUser user) { | |
// @AuthでCookie認証後にUserが取得される | |
return new MypageTopView(MypageTopView.Template.FREEMARKER,user); | |
} | |
} | |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package jp.hoge.app.resources; | |
import java.net.URI; | |
import java.net.URISyntaxException; | |
import javax.ws.rs.FormParam; | |
import javax.ws.rs.GET; | |
import javax.ws.rs.POST; | |
import javax.ws.rs.Path; | |
import javax.ws.rs.PathParam; | |
import javax.ws.rs.Produces; | |
import javax.ws.rs.core.MediaType; | |
import javax.ws.rs.core.NewCookie; | |
import javax.ws.rs.core.Response; | |
import jp.hoge.app.views.LoginView; | |
@Path("/login") | |
public class LoginResource { | |
@GET | |
@Path("/") | |
@Produces(MediaType.TEXT_HTML) | |
public LoginView getLoginView() { | |
return new LoginView(LoginView.Template.FREEMARKER); | |
} | |
@POST | |
@Path("/signin") | |
public Response signup(@FormParam("email") String email , @FormParam("password") String password) { | |
// アイパス認証 | |
if ("test".equals(email) && "test".equals(password)) { | |
// Cookie生成 (これだとブラウザ閉じるまでの間だけ) | |
NewCookie cookies = new NewCookie("sid","abcdefg","/",null,"",NewCookie.DEFAULT_MAX_AGE,false);; | |
try { | |
// Cookieセットしてマイページ画面へリダイレクト | |
return Response.seeOther(new URI("/mypage")).cookie(cookies).build(); | |
} catch (URISyntaxException e) { | |
e.printStackTrace(); | |
} | |
} | |
try { | |
// 認証失敗したらログイン画面へ戻る | |
return Response.seeOther(new URI("/login")).build(); | |
} catch (URISyntaxException e) { | |
e.printStackTrace(); | |
} | |
return Response.serverError().build(); | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package jp.hoge.app.views; | |
import io.dropwizard.views.View; | |
public class LoginView extends View { | |
public enum Template { | |
FREEMARKER("login.ftl"); | |
private String templateName; | |
private Template(String templateName){ | |
this.templateName = templateName; | |
} | |
public String getTemplateName(){ | |
return templateName; | |
} | |
} | |
public LoginView(LoginView.Template templateName) { | |
super(templateName.getTemplateName()); | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package jp.hoge.app.views; | |
import jp.hoge.app.core.HogeUser; | |
import io.dropwizard.views.View; | |
public class MypageTopView extends View { | |
private final HogeUser user; | |
public enum Template { | |
FREEMARKER("mypage_top.ftl"); | |
private String templateName; | |
private Template(String templateName){ | |
this.templateName = templateName; | |
} | |
public String getTemplateName(){ | |
return templateName; | |
} | |
} | |
public MypageTopView(MypageTopView.Template templateName,HogeUser user) { | |
super(templateName.getTemplateName()); | |
this.user = user; | |
} | |
public HogeUser getUser() { | |
return user; | |
} | |
} | |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<#-- @ftlvariable name="" type="jp.hoge.app.views.LoginView" --> | |
<html> | |
<head><meta charset="UTF-8"></head> | |
<body> | |
<h1>ログイン</h1> | |
<form action="login/signup" method="post"> | |
<p>Eメール : <input type="text" name="email" size="40"></p> | |
<p>パスワード : <input type="password" name="password" size="40"></p> | |
<input type="submit" value="ログイン"> | |
</form> | |
</body> | |
</html> |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<#-- @ftlvariable name="" type="jp.hoge.app.views.LoginView" --> | |
<html> | |
<head> | |
<meta charset="UTF-8"> | |
</head> | |
<body> | |
<!-- calls getUser().getUserId() and sanitizes it --> | |
<h1>Hello, ${user.userId?html}!</h1> | |
</body> | |
</html> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment