大多数项目的权限管理都是通过Role来实现的。 如果当前用户拥有指定的Role才能进行相应的操作。这一节就学习如何在Restlet中使用Role进行权限控制。
首先,定义一个Account类,模拟我们系统中的用户。
public class Account { private String username ; private String password ; private String email ; private String[] roles ; public Account(String username, String password, String email) { super(); this.username = username; this.password = password; this.email = email; } public Account(String username, String password, String email, String[] roles) { super(); this.username = username; this.password = password; this.email = email; this.roles = roles; } public Account() { super(); } public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } public String getEmail() { return email; } public void setEmail(String email) { this.email = email; } public String[] getRoles() { return roles; } public void setRoles(String[] roles) { this.roles = roles; } }
然后是AccountManager(模拟数据库操作)
public class AccountManager { private List<Account> accounts = new ArrayList<Account>() ; { //初始化一些账户 accounts.add(new Account("111", "111", "[email protected]", new String[]{"Admin" , "Common" , "Manager"})) ; accounts.add(new Account("222", "222", "[email protected]", new String[]{"Common"})) ; accounts.add(new Account("333", "333", "[email protected]", new String[]{"Common"})) ; accounts.add(new Account("444", "444", "[email protected]", new String[]{"Manager" , "Common"})) ; } /** * 根据用户名查找用户 */ public Account findUserByName(String username){ for (Account account : accounts) { if(account.getUsername().equals(username)){ return account ; } } return null ; } /** * 根据用户名查找用户所拥有的权限 */ public String[] findRoleByUsername(String username){ for (Account account : accounts) { if(account.getUsername().equals(username)){ return account.getRoles() ; } } return null ; } }
/** * 自定义的校验器 */ public class MySecretVerifier extends SecretVerifier{ private AccountManager accountManager = new AccountManager() ; @Override public int verify(String identifier, char[] secret) { System.out.printf("username:%s password:%s%n" , identifier , new String(secret) ); Account account = accountManager.findUserByName(identifier); if(account != null){ if(compare(account.getPassword().toCharArray(), secret)){ return RESULT_VALID ; } } return RESULT_INVALID; } }
接下来编写服务端资源
public class MovieServerResource extends ServerResource implements MovieResource{ public String uploadMovie(Movie movie) throws IOException{ String result = String.format("upload movie{name:%s size:%d minutes:%d} success!" , movie.getName() , movie.getSize(), movie.getMinutes()); return result ; } @Override public Representation getMovieInfo() { //如果拥有Manager或Admin的Role才能访问本方法 if(isInRole("Manager") || isInRole("Admin") ){ return new StringRepresentation("movie info"); }else{ return new StringRepresentation("Permission Denied"); } } }
public class MovieApplication extends Application{ private AccountManager accountManager = new AccountManager() ; public MovieApplication(){ setAuthor("zhoufeng"); /* * 在Application中,必须同时也包含所有该Application会用到的Role * 从源码IsInRole()方法的实现就能明白 * public boolean isInRole(String roleName) { return getClientInfo().getRoles().contains( getApplication().getRole(roleName)); } * */ getRoles().add(new Role("Common")); getRoles().add(new Role("Manager")); getRoles().add(new Role("Admin")); } /** * 注意:Router 与 ChallengeAuthenticator 均是Restlet的子类 */ @Override public Restlet createInboundRoot() { Router router = new Router(getContext()); //绑定资源 router.attach("/" , MovieServerResource.class); //创建认证器 ChallengeAuthenticator authenticator = new ChallengeAuthenticator(getContext(), ChallengeScheme.HTTP_BASIC, "Movie Realm"); /** * 注意: * 当客户端访问资源时,首先经过Verifier验证用户名与密码,如果校验失败,就会直接返回客户端error:401 Unauthorized校验失败 * 然后再通过Enroler为ClientInfo中User查询出Roles * 最后在ServerResource中就可以通过isInRole()方法判断访问该方法的当前用户是否拥有指定的角色。 */ //使用自定义的验证器 authenticator.setVerifier(new MySecretVerifier()); /* 登记用户所拥有的角色 */ authenticator.setEnroler(new Enroler() { @Override public void enrole(ClientInfo clientInfo) { String[] roles = accountManager. findRoleByUsername(clientInfo.getUser().getIdentifier()); for (String role : roles) { clientInfo.getRoles().add(getApplication().getRole(role)) ; } } }); //将路由器放在认证器之后 authenticator.setNext(router); //返回认证器 return authenticator ; } }
public class MovieServer { public static void main(String[] args) throws Exception { Component comp = new Component() ; comp.getServers().add(Protocol.HTTP , 8888) ; MovieApplication movieApp = new MovieApplication() ; comp.getDefaultHost().attach(movieApp); comp.start(); } }
public class MovieClient { /** * 不使用用户名密码直接访问Get方法,将会抛出异常 */ @Test public void test01() throws IOException{ ClientResource cr = new ClientResource("http://localhost:8888/"); cr.get().write(System.out); } /** * 加入用户名密码访问Get方法,成功得到返回值 */ @Test public void test02() throws IOException{ ClientResource cr = new ClientResource("http://localhost:8888/"); cr.setChallengeResponse(ChallengeScheme.HTTP_BASIC , "111", "111"); cr.get().write(System.out); } }