2017-12-13 5 views
0

私は、ユーザーを認証し、jsonwebtokenを取得し、保護されたURLにアクセスできました。私は "user"または "admin"の役割を持つトークンにクレームを残しています。ユーザーを確認した後でできることができるようにするのが理想的ですが、ユーザーの役割や役割に基づいて役割を維持し、それらに基づいてAPI内の特定のURLを保護します。私は以下の設定をしています。トークンの役割に基づいて差別化する特定のURLにセキュリティを適用するにはどうすればよいですか?ロールベースのセキュリティJsonwebtokenに基づいて、Springブートで異なるコントローラに異なるロールを使用する

Package com.vicentex.api; 

// imports excluded for brevity 

@SpringBootApplication 
public class VicentexTradingApiApplication { 

@Bean 
public FilterRegistrationBean jwtFilter() { 
    final FilterRegistrationBean registrationBean = new FilterRegistrationBean(); 
    registrationBean.setFilter(new JwtFilter()); 
    registrationBean.addUrlPatterns("/api/*"); 

    return registrationBean; 
} 

public static void main(String[] args) { 
    SpringApplication.run(VicentexTradingApiApplication.class, args); 
} 
} 

///////////////////////////////////////////////////////////////////// 
///////////////////////////////////////////////////////////////////// 

@RestController 
public class UserController { 

    @Autowired 
    private UserService userService; 

    @RequestMapping(value = "/api/users", method = RequestMethod.GET) 
    List<User> getAllUsers(){ 
     return this.userService.getAllUsers(); 
    } 

    @RequestMapping(value = "/api/users/{userName}",method = RequestMethod.GET) 
    User getUser(@PathVariable String userName) { 
     return this.userService.getUser(userName); 
    } 

    @RequestMapping(value = "/api/users", method = RequestMethod.POST) 
    void addUser(@RequestBody User user) { 
     this.userService.addUser(user); 
    } 

    @RequestMapping(value = "/api/users", method = RequestMethod.PUT) 
    void updateUser(@RequestBody User user) { 
     this.userService.updateUser(user); 
    } 


    @RequestMapping(value = "/api/users/{userName}", method = RequestMethod.DELETE) 
    void deleteUser(@PathVariable String userName) { 
     this.userService.deleteUser(userName); 
    } 

    @RequestMapping(value = "/register", method = RequestMethod.POST) 
    public User registerUser(@RequestBody User user) { 
     userService.addUser(user); 
     return user; 
    } 


    @RequestMapping(value = "/login", method = RequestMethod.POST) 
    public String login(@RequestBody User login) throws ServletException { 

     System.out.println("Controller Secret: " + Constants.secretKey); 

     String jwtToken = ""; 

     if (login.getUserName() == null || login.getPassword() == null) { 
      throw new ServletException("Please fill in username and password"); 
     } 

     String userName = login.getUserName(); 
     String password = login.getPassword(); 

     User user = userService.Authenticate(userName, password); 


     if (user == null) { 
      throw new ServletException("User not found."); 
     } 

     String pwd = user.getPassword(); 

     if (!password.equals(pwd)) { 
      throw new ServletException("Invalid login. Please check your name and password."); 
     } 


     if (user.isAdmin()) { 

      jwtToken = Jwts.builder() 
       .setSubject(userName) 
       .claim("roles", "admin") 
       .setIssuedAt(new Date()) 
       .signWith(SignatureAlgorithm.HS256, Constants.secretKey) 
       .compact(); 
     } else { 

      jwtToken = Jwts.builder() 
       .setSubject(userName) 
       .claim("roles", "user") 
       .setIssuedAt(new Date()) 
       .signWith(SignatureAlgorithm.HS256, Constants.secretKey) 
       .compact(); 

     } 

     return jwtToken; 
    } 


    } 

    //////////////////////////////////////////////////////////////////// 
    //////////////////////////////////////////////////////////////////// 

    package com.vicentex.api.models; 

    @Document(collection = "Users") 
    public class User { 

    @Id 
    private ObjectId id; 
    private String userName; 
    private String fullName; 
    private String email; 
    private String password; 
    private String image; 
    private boolean isAdmin = false; //flagged for simplicity. Will be an array 

    Account acct; 

    @DBRef 
    List<Transaction> transactions; 


    public User() { 
     super(); 
    } 

    public User(String userName, String fullName, String email, String password, String image) { 
     super(); 
     this.userName = userName; 
     this.fullName = fullName; 
     this.email = email; 
     this.password = password; //note to remember to encrypt on creation 
     this.image = image; 
    } 


    public String getUserName() { 
     return userName; 
    } 

    public void setUserName(String userName) { 
     this.userName = userName; 
    } 
    public String getFullName() { 
     return fullName; 
    } 
    public void setFullName(String fullName) { 
     this.fullName = fullName; 
    } 
    public String getEmail() { 
     return email; 
    } 
    public void setEmail(String email) { 
     this.email = email; 
    } 
    public String getPassword() { 
     return password; 
    } 
    public void setPassword(String password) { 
     this.password = password; 
    } 
    public String getImage() { 
     return image; 
    } 
    public void setImage(String image) { 
     this.image = image; 
    } 

    public boolean isAdmin() { 
     return isAdmin; 
    } 

    public void setAdmin(boolean isAdmin) { 
     this.isAdmin = isAdmin; 
    } 

    public Account getAcct() { 
     return acct; 
    } 

    public void setAcct(Account acct) { 
     this.acct = acct; 
    } 

    public List<Transaction> getTransactions() { 
     return transactions; 
    } 

    public void setTransactions(List<Transaction> transactions) { 
     this.transactions = transactions; 
    } 

} 

答えて

0

春には、メソッドレベルで@PreAuthorize("hasRole('somrole')")アノテーションを使用します。 Springは「権限」の主張に役割が期待されています。

+0

私が正しくあなたを理解してあれば、その後、私は変更する必要があります役割を示し、その後、所望のアクセスに関して任意のコントローラを装飾するか? –

+0

はい、ロールの配列です。あなたのコールの 'claim(" authorities "、" user ")が配列に入れられるかどうかは不明です。 – tsolakp

0

@PreAuthorizeを利用するために、私はpom.xmlにSpring Securityを依存関係として含める必要がありました。これは、APIのパスワードを私に求めていました。さらに悪いことに、私がパスワードを無効にすると、基本的に目的を破った。私は、単にhttps上のセキュリティ機構としてjsonwebtokenを利用し、トークン内のロールに基づいてURLの特定のサブセットを保護したいと考えました。だから、私が実際にやってしまったことは、このでした:技術的には

public class JwtFilter extends GenericFilterBean { 

    public void doFilter(final ServletRequest req, final ServletResponse res, final FilterChain chain) 
     throws IOException, ServletException { 

    System.out.println("Secret Key: " + Constants.secretKey); 

    final HttpServletRequest request = (HttpServletRequest) req; 
    final HttpServletResponse response = (HttpServletResponse) res; 
    final String authHeader = request.getHeader("authorization"); 

    if ("OPTIONS".equals(request.getMethod())) { 

     response.setStatus(HttpServletResponse.SC_OK); 
     chain.doFilter(req, res); 

    } else { 

     if (authHeader == null || !authHeader.startsWith("Bearer ")) { 
      throw new ServletException("Missing or invalid Authorization header"); 
     } 

     final String token = authHeader.substring(7); 

     try { 

      final Claims claims = Jwts.parser().setSigningKey(Constants.secretKey).parseClaimsJws(token).getBody(); 

      String[] roles = claims.get("roles").toString().split(","); 

      if (request.getRequestURI().contains("/api/")) { 
       if (!Arrays.asList(roles).contains("user")) { 
        System.out.println("ROLES: " + claims.get("roles")); 
        throw new ServletException("A minimum security credential of 'user' is required to access this resource!"); 
       } 
      } 

      if (request.getRequestURI().contains("/api/admin")) { 
       if (!Arrays.asList(roles).contains("admin")) { 
        System.out.println("ROLES: " + claims.get("roles")); 
        throw new ServletException("This route is restricted to administrators only"); 
       } 
      } 


      request.setAttribute("claims", claims); 

     } catch (final SignatureException e) { 
      throw new ServletException("Invalid token"); 
     } 

     chain.doFilter(req, res); 
    } 
    } 
} 

/////////////////////////////////////////////////////////////// 
/////////////////////////////////////////////////////////////// 
// In addition, I changed the login code in the user controller 

if (user.isAdmin()) { 

     jwtToken = Jwts.builder() 
       .setSubject(userName) 
       .claim("roles", "admin,user") 
       .setIssuedAt(new Date()) 
       .signWith(SignatureAlgorithm.HS256, Constants.secretKey) 
       .compact(); 
    } else { 

     jwtToken = Jwts.builder() 
       .setSubject(userName) 
       .claim("roles", "user") 
       .setIssuedAt(new Date()) 
       .signWith(SignatureAlgorithm.HS256, Constants.secretKey) 
       .compact(); 

    } 

、私が今までになくても、要求されたURIに基づいて、各1を通じて役割/ URIのセキュリティマッピングを持つ収集、およびループを作成することができますコントローラを装飾する。当局は文字列であることと .claim(「役割」、「利用者」).claimする(「役割」、当局) []:

関連する問題