Sunday, July 28, 2013

Permission based authorization with OAuth 10a

OAuth 10a deals with roal based authorization. 
Can we do the permission based authorization with oauth 10a ?

That is can we authorize a URL pattern, can we authorize frequency of request URL 
Or can we authorize particulate client IP to access the resource

The easiest way is to write a custom expression voter as below

public class CExpressionVoter implements AccessDecisionVoter<FilterInvocation> {
    public int vote(Authentication authentication, FilterInvocation fi, Collection<ConfigAttribute> attributes) {
        assert authentication != null;
        assert fi != null;
        assert attributes != null;

        if(authentication.getPrincipal()!=null ) {
        Object principal = authentication.getPrincipal();
        if(principal instanceof UserDetails) {
        UserDetails userDetails = (UserDetails)principal;
        if(userDetails.getUsername().equalsIgnoreCase("anonymousUser")){
        return -1;
        } else {
        Collection<? extends GrantedAuthority> authorities = userDetails.getAuthorities();
          int i = -1;
        for (GrantedAuthority grantedAuthority : authorities) {
String uriAuthorityPattern = grantedAuthority.getAuthority().toLowerCase();
String uriRequest = fi.getRequestUrl().toLowerCase();
String fullRequestUrl = fi.getFullRequestUrl();

String delimiters = "/\\s*|\\?\\s*";
String[] uriPatternArray = uriRequest.split(delimiters);
String uriPattern = null;
if(uriPatternArray !=null & uriPatternArray.length >=2) {
uriPattern = uriPatternArray[1];
}
// This is the sample to check the URL pattern. Likewise you can do other authentications, All the autorities can be loaded to
// user detail object using a custom user detail service, sample given below
if (uriPattern!=null & uriPattern.equalsIgnoreCase(uriAuthorityPattern)){
i = 1; break;
} else {
i = -1;
}
}
        return i;        
        }
       
        if (principal instanceof String) {
        if(((String) principal).equalsIgnoreCase("anonymousUser")){
        return -1;
        }
        }
        }
        return 1;
    }
    public boolean supports(ConfigAttribute attribute) {
    return true;
    }

    public boolean supports(Class<?> clazz) {
        return clazz.isAssignableFrom(FilterInvocation.class);
    }
}

Custom User Detail Service
public class CUserDetailService implements UserDetailsService {
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
ArrayList<String> authority  = new ArrayList<String>();
// Get the values from the database and add as arrayList
UserDetails result = new CustomUserDetails(findById, authority);
return result;
}

}

Custom User Details

public class CustomUserDetails implements UserDetails {
private String userName;
private String password;
private Collection<GrantedAuthority> grantedAuthorities;

public CustomUserDetails(CustomUser user, List<String> authority){
this.grantedAuthorities = new ArrayList<GrantedAuthority>();
for (String p : authority) {
GrantedAuthority ga = new SimpleGrantedAuthority(p);
this.grantedAuthorities.add(ga);
}
}

public Collection<? extends GrantedAuthority> getAuthorities() {
return this.grantedAuthorities;
}

// write inherited methods for UserDetails
}

Custom Secure Resource Filter
// this is a dummy implementation
public class CSecureResourceFilter implements FilterInvocationSecurityMetadataSource {
public Collection<ConfigAttribute> getAllConfigAttributes() {
StringBuilder rolesStringBuilder = new StringBuilder();
rolesStringBuilder.append("USER1");
List<ConfigAttribute> createListFromCommaDelimitedString = SecurityConfig.createListFromCommaDelimitedString(rolesStringBuilder.toString());
return createListFromCommaDelimitedString;
}

public Collection<ConfigAttribute> getAttributes(Object filter) throws IllegalArgumentException {
StringBuilder rolesStringBuilder = new StringBuilder();
rolesStringBuilder.append("USER1");
return SecurityConfig.createListFromCommaDelimitedString(rolesStringBuilder.toString());
}
public boolean supports(Class<?> arg0) {
return true;
}
}


Spring security configuration file

..

<beans:bean id="accessDecisionManager" class="org.springframework.security.access.vote.AffirmativeBased">
<beans:constructor-arg name="decisionVoters">
<beans:list>
<beans:bean class="..................CExpressionVoter" />
</beans:list>
</beans:constructor-arg> 
</beans:bean>

<http use-expressions="true" auto-config='true' access-denied-page="/login.jsp" > 
<form-login authentication-failure-url="/login.jsp" default-target-url="/index.jsp" login-page="/login.jsp" login-processing-url="/login.do" />
<custom-filter before="FILTER_SECURITY_INTERCEPTOR" ref="filterSecurityInterceptor" /> 
</http> 

<beans:bean id="customUserDetailService" class=".....CUserDetailService" /> 

<authentication-manager alias="authenticationManager">
<authentication-provider user-service-ref="customUserDetailService"/> 
</authentication-manager>

<beans:bean id="customSecureResourceFilter" class=".......CSecureResourceFilter"/>


<beans:bean id="filterSecurityInterceptor" class="org.springframework.security.web.access.intercept.FilterSecurityInterceptor">
<beans:property name="authenticationManager" ref="authenticationManager"/>
<beans:property name="accessDecisionManager" ref="accessDecisionManager"/>
<beans:property name="securityMetadataSource" ref="customSecureResourceFilter"/>

</beans:bean>

Tuesday, June 25, 2013

Mock with Jsonpath and Spring MVC

When REST controller returns JSON here is the method to test it

JSON String

[{"id":1,"name":"Sam"},{"id":2,"name":"David"}]

Test

    MockMvc mockMvc;

@Autowired
protected WebApplicationContext wac;

@Before
public void setup() {
mockMvc = MockMvcBuilders.webAppContextSetup(wac).build();
}


@Test
public void shouldGiveSingleDataSetForAvailabilityTypeService() {
try {
 mockMvc.perform(get("/person/1").accept(MediaType.APPLICATION_JSON)).andExpect(status().isOk()).andExpect(jsonPath("name", is("Sam")));
 mockMvc.perform(get("/person/2").accept(MediaType.APPLICATION_JSON)).andExpect(status().isOk()).andExpect(jsonPath("name", is("David")));

} catch (Exception e) {
log.error(e.getMessage(), e);
fail();
}

Sunday, June 16, 2013

Testing with Spring 3.2

Spring MVC gives a test framework which MockMvc provides simulation of a servlet container. Its like your running on a mock server. This will help to test all your REST controllers from junit

@WebAppConfiguration
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = { "classpath:dispatch-servlet.xml" })
public class XXXXXXXXXControllerTest {
@Autowired
XXXXXXController xxxxxxxxxController;       
...

MockMvc mockMvc = MockMvcBuilders.standaloneSetup(xxxxxxxxxController).build();
...
 @Test
 public void shouldXXXXXXXXXXXXXXXXXXXXXX() {
     mockMvc.perform(get("/a/1").accept(MediaType.APPLICATION_JSON)).
                                         andExpect(status().isOk())
   .andExpect(content().string("yyyyyyyyyyyyyyyyyyy"));

}
}
Above is only if we know the name of the controller class. This is good for unit testing the controller classes

OR if you not need to use a given spring config you can use  WebApplicationContext as below

@WebAppConfiguration
public class YYYYYYYYYY{
    MockMvc mockMvc;
@Autowired
protected WebApplicationContext wac;
@Before
public void setup() {
mockMvc = MockMvcBuilders.webAppContextSetup(wac).build();
}
protected void shouldXXXXXXXXX() {
getMockMvc().perform(get(restCall)).andExpect(status().isOk());

}

}

Wednesday, June 12, 2013

JSONP response from Spring MVC

How to get a JSONP response from Spring MVC

The best and easy way to do this is attach a filter to HTTP response.

Here is a working example for this


  • Create a filter class and its supported utility classes


public class JsonpBoundryFilter implements Filter {   
public void init(FilterConfig fConfig) throws ServletException {} 
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
HttpServletRequest httpRequest = (HttpServletRequest) request;
HttpServletResponse httpResponse = (HttpServletResponse) response; 
@SuppressWarnings("unchecked")
Map<String, String[]> parms = httpRequest.getParameterMap(); 
if(parms.containsKey("callback")) {
OutputStream out = httpResponse.getOutputStream(); 
GenericResponseWrapper wrapper = new GenericResponseWrapper(httpResponse); 
chain.doFilter(request, wrapper);            
byte[] bytes1 = new String(parms.get("callback")[0] + "(").getBytes();
byte[] bytes2 = wrapper.getData();
byte[] bytes3 = new String(");").getBytes();            
ByteBuffer byteBuffer = ByteBuffer.allocate(bytes1.length + bytes2.length + bytes3.length);
byteBuffer.put(bytes1);
byteBuffer.put(bytes2);
byteBuffer.put(bytes3);            
byte[] jsonpResponse = byteBuffer.array();
wrapper.setContentType("text/javascript;charset=UTF-8");
wrapper.setContentLength(jsonpResponse.length);
out.write(jsonpResponse); 
out.close();
} else {
chain.doFilter(request, response);
}

public void destroy() {}
}

public class GenericResponseWrapper extends HttpServletResponseWrapper { 
private ByteArrayOutputStream output;    
private FilterServletOutputStream filterStream;
private PrintWriter printWriter;    
private int contentLength;
private String contentType;
 
public GenericResponseWrapper(HttpServletResponse response) {
super(response); 
output = new ByteArrayOutputStream();
filterStream = new FilterServletOutputStream(output);
printWriter = new PrintWriter(output, true);
}  
public byte[] getData() {
return output.toByteArray();
}  
public ServletOutputStream getOutputStream() {
return filterStream;
}  
public PrintWriter getWriter() {
return printWriter;
}  
public void setContentLength(int length) {
this.contentLength = length;
super.setContentLength(length);
}  
public int getContentLength() {
return contentLength;
}  
public void setContentType(String type) {
this.contentType = type;
super.setContentType(type);
}  
public String getContentType() {
return contentType;
}
}

public class FilterServletOutputStream extends ServletOutputStream {
private DataOutputStream stream;
public FilterServletOutputStream(OutputStream output) {
stream = new DataOutputStream(output);
}
public void write(int b) throws IOException {
stream.write(b);
}
public void write(byte[] b) throws IOException {
stream.write(b);
}
public void write(byte[] b, int off, int len) throws IOException {
stream.write(b, off, len);
}
}


  • Add the following configurations to your web.xml

<filter>
<filter-name>jsonpCallbackFilter</filter-name>
<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
</filter>
<filter-mapping>
<filter-name>jsonpBroudryFilter</filter-name> // this name should be in your spring config
<url-pattern>/*</url-pattern>
</filter-mapping>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value> /WEB-INF/dispatch-servlet.xml</param-value>
</context-param>
 <listener> 
<listener-class>
                  org.springframework.web.context.ContextLoaderListener
   </listener-class>
</listener>


  • Add following to your spring config as


<bean id="jsonpCallbackFilter" class="com.....JsonpBoundryFilter" />

Sound easy.............  :)

Thursday, May 23, 2013

When Amazon SQS throws Exception..


When exception occurs when try to execute some data from AWS SQS we can rollback the changes/ do any other stuff like this

1. Write a call extending SimpleMessageListenerContainer

public class BoundryMessageListenerContainer extends SimpleMessageListenerContainer {
protected void rollbackOnExceptionIfNecessary(Session session, Throwable ex) throws JMSException {
try {
if (session != null & ex.getMessage() != null) {

JmsUtils.rollbackIfNecessary(session);

String message = ex.getLocalizedMessage();

if (message != null & message.length() > 0) {
// DO WHAT EVER YOU NEED TO DO 
}
}
} catch (IllegalStateException ex2) {
} catch (JMSException ex2) {
} catch (RuntimeException ex2) {
} catch (Error err) {
}
}
}

2. Add this to spring configuration

<bean id="container"
class="...........BoundryMessageListenerContainer">
<property name="connectionFactory" ref="connectionFactory" />
<property name="messageListener" ref="listener" />
<property name="destination" ref="boundryQueue" />
</bean>

Number of messages in AWS SQS



1. Spring configuration

<bean id="amazonSQSClient" class="com.amazonaws.services.sqs.AmazonSQSClient">
<constructor-arg>
<bean class="com.amazonaws.auth.BasicAWSCredentials">
<constructor-arg value="${amazon.access.key}" />
<constructor-arg value="${amazon.access.secret}" />
</bean>
</constructor-arg>
</bean>

2. Write your java code as


@Autowired
AmazonSQSClient amazonSQSClient;

..


public int getNoOfMessagesInQueue() {
AmazonSQS sqs = amazonSQSClient;
sqs.setEndpoint(endPoint);
GetQueueAttributesRequest getQueueAttributesRequest = new GetQueueAttributesRequest(sqsUrl);
Collection<String> attributeNames = new ArrayList<String>();
attributeNames.add("All");
getQueueAttributesRequest.setAttributeNames(attributeNames);
GetQueueAttributesResult queueAttributes = sqs.getQueueAttributes(getQueueAttributesRequest);
return Integer.parseInt(queueAttributes.getAttributes().get("ApproximateNumberOfMessages"));
}

Monday, May 6, 2013

Write to separate Log files using Logback

There may be many instance you may have to write your logs to separate log files. Here are the easy steps to do that


  • Write a new logger in the existing log configuration file
<!-- Plain Text Rolling Appender for Custom logger file -->
    <appender name="SEPERATE_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <Append>true</Append>
        <File>seperate.log</File>
        <encoder>
            <pattern>%d{yyyy-MM-dd HH:mm:ss} %c{1} [%p] %m%n</pattern>
        </encoder>
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <fileNamePattern>seperate.log.%d{yyyy-MM-dd}</fileNamePattern>
            <maxHistory>30</maxHistory>
        </rollingPolicy>
    </appender>
    
    <!-- additivity=false ensures seperate ata only goes to the seperate log -->
    <logger name="seperate" level="DEBUG" additivity="false">
        <appender-ref ref="SEPERATE_FILE"/>
    </logger>

  • Add the new logger where every you need in the java class as 
private static final Logger log = LoggerFactory.getLogger("seperate");
  • Starts logging as log.info..., log.debug..
  • Cool ha