-
Notifications
You must be signed in to change notification settings - Fork 29
Authentication
Xueping edited this page May 29, 2020
·
10 revisions
To implement Role-based authorization with Shiro and JWT. See https://github.com/dicoth/dicoth.
class AdminCmsRealm : AuthorizingRealm {
override
bool supports(AuthenticationToken token) {
JwtToken jt = cast(JwtToken)token;
return jt !is null;
}
override protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) {
string tokenString = token.getPrincipal();
string username = JwtUtil.getUsername(tokenString);
// To retrieve the user info from username
// Valid the user using JWT
if(JwtUtil.verify(tokenString, username, userModel.password)) {
SimpleAuthenticationInfo info = new SimpleAuthenticationInfo(userModel, credentials, getName());
return info;
} else {
throw new WrongPasswordException(username);
}
}
override protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
User user = cast(User) principals.getPrimaryPrincipal();
if(user is null) {
warning("no principals");
return null;
}
SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
// To retrieve all the roles for the user from database
Role[] userRoles = roleRep.getUserRoles(user.id);
....
// Recording the permissions based on each role
foreach(Role r; userRoles) {
// roles
info.addRole(r.name);
// permissions
info.addStringPermission("*"); // for administrator
info.addStringPermission("permission"); // specific permission
}
return info;
}
}
The AuthServiceProvider uses Hunt-Cache to cache all the authorization informations.
class DicothAuthServiceProvider : AuthServiceProvider {
override void register() {
serviceContainer().register!(AuthorizingRealm, AdminCmsRealm).newInstance;
}
}
The user-defined AuthServiceProvider should be register at the main entrance of the application.
app.register!DicothAuthServiceProvider;
// Retrieve the user's info from database
User userModel = userRepository.findByEmail(username);
// Generate a JWT token based on the username and password
string checkSalt = generateUserPassword(password, userModel.salt);
string tokenString = JwtUtil.sign(username, checkSalt);
// Set the token to cookie
Cookie sessionCookie = new Cookie("__auth_token__", tokenString, 86400);
override Response onProcess(Request request, Response response) {
enum TokenHeader = "Bearer ";
string tokenString = request.header(HttpHeader.AUTHORIZATION);
tokenString = tokenString[TokenHeader.length .. $];
string sessionId = request.cookie("ShiroSessionId");
if(!sessionId.empty) {
Subject subject = SecurityUtils.newSubject(sessionId, request.host());
try {
JwtToken token = new JwtToken(tokenString);
subject.login(token);
} catch (AuthenticationException e) {
warning(e);
} catch(Exception ex) {
warning(ex);
}
if(subject.isAuthenticated()) {
// Set the authenticated user to the current request
request.setAttribute(Subject.DEFAULT_NAME, cast(Object)subject);
return null;
}
if (subject.hasRole("admin")) {
// do somthing
}
if (subject.isPermitted("delete")) {
// do somthing
}
return new RedirectResponse(request, url("system.user.login", null, "admin"));
}
@Action Response logout() {
string sessionId = request.cookie("ShiroSessionId");
Subject subject = SecurityUtils.newSubject(sessionId, request.host());
subject.logout();
Cookie sessionCookieToken = new Cookie("__auth_token__","",0);
return new RedirectResponse(this.request(), "/")
.withCookie(sessionCookieToken);
}