How to access username principle in a cxf-se with ws-security? - esb

I finally got the Ws-Security working with CXF-BC & CXF-SE combination. I'm now trying to access the username from the soap header in the SE to check permission and ownership of the user calling a operation, but there seems to be no way of doing that. I know that once a message get passed from the BC to the SE, it just takes the SOAP body and wraps in a JBI msg. Is there anyway to stuff the soap header in the JBI msg or, have the BC truly forward the SOAP msg as it has received it. I've tried to disable the JBIwrapper on the BC and SE, while it sends the message as SOAP it only sends the body of the original msg san header.
I'm not sure why this is so hard and complex to do this on the BC/SE, since it was relatively easy to do with JAXWS.
Thanks

This answer came from Freeman over at the Servicemix-user mailing-list.
Basically you have to set a JBI property on a BC's ininterceptor, and then you can access it over on the SE.
ex. ininterceptor
public class SaveSubjectInterceptor extends AbstractPhaseInterceptor {
public SaveSubjectInterceptor() {
super(Phase.PRE_INVOKE);
}
public void handleMessage(Message message) throws Fault {
List<Object> results = (List<Object>) message.get(WSHandlerConstants.RECV_RESULTS);
if (results == null) {
return;
}
for (Iterator iter = results.iterator(); iter.hasNext();) {
WSHandlerResult hr = (WSHandlerResult) iter.next();
if (hr == null || hr.getResults() == null) {
return;
}
boolean authenticated = false;
for (Iterator it = hr.getResults().iterator(); it.hasNext();) {
WSSecurityEngineResult er = (WSSecurityEngineResult) it.next();
Object wstockPrincipal = er.get(WSSecurityEngineResult.TAG_PRINCIPAL);
if (er != null && wstockPrincipal instanceof WSUsernameTokenPrincipal) {
WSUsernameTokenPrincipal p = (WSUsernameTokenPrincipal) wstockPrincipal;
NormalizedMessage nm = (NormalizedMessage) message.getContent(NormalizedMessage.class);
nm.setProperty("Username", p.getName());
break;
}
}
}
}
}
ex of SE pojo
#Resource
private WebServiceContext wsContext;
...
...
javax.xml.ws.handler.MessageContext ctx = wsContext.getMessageContext();
org.apache.cxf.message.Message message = ((org.apache.cxf.jaxws.context.WrappedMessageContext) ctx).getWrappedMessage();
String username = (String) message.get("Username");
I hope this helps someone else.
I have a full example here w/ ws-security policy, but it is only there for a limited amount of time.

Related

How ro fix "java.lang.AssertionError: expected:<String> but was:<null> "?

I'm trying to test my service and an some point I received an error when I did the assertEquals
This is my test
#Test
public void createNewCommentCreatesNewDTOIfNoDTOExists() {
CommentDTO commentDTO = mock(CommentDTO.class);
MergedScopeKey mergedScopeKey = mock(MergedScopeKey.class);
//set merged scope key
sut.setInput(mergedScopeKey);
String commentText = "commentText";
//define behaviour
when(commentApplicationService.createCommentDTO(mergedScopeKey, commentText)).thenReturn(commentDTO);
sut.createNewComment(commentText);
//test the functionality
assertNotNull(commentDTO);
assertEquals(commentText, commentDTO.getCommentText());
//test the behavior
verify(commentApplicationService).createCommentDTO(mergedScopeKey, commentText);
}
And this is my method that I wanted to test:
protected void createNewComment(String commentText) {
CommentDTO commentDTO = commentApplicationService.getDTOComment(mergedScopeKey);
if (commentDTO == null) {
commentApplicationService.createCommentDTO(mergedScopeKey, commentText);
} else {
updateComment(commentDTO, commentText);
}
}
Do you have any ideas what I do wrong ?
You define behaviour:
when(commentApplicationService.createCommentDTO(mergedScopeKey, commentText)).thenReturn(commentDTO);
But in your test you call:
CommentDTO commentDTO = commentApplicationService.getDTOComment(mergedScopeKey);
This is a different method, you receive null here.
Even if you fix this, you call updateComment. It is highly unlikely that your production code sets expectations on the passed in mock, thus you will always receive null from commentDto.getCommentText()
Consider using a real class instead of a mock for DTO classes.

Random System.Net.Mail.SmtpFailedRecipientsException exception - relay account office365

We have an application that runs on a Windows Server 2008 machine. It sends emails out using an office365 smtp relay account. However, all the emails are not sent successfully. We randomly get these two exceptions on emails being sent out on the smtp.Send call:
System.Net.Mail.SmtpFailedRecipientsException: Unable to send to all recipients. ---> System.Net.Mail.SmtpFailedRecipientException: Mailbox unavailable. The server response was: 5.7.64 TenantAttribution; Relay Access Denied
System.Net.Mail.SmtpFailedRecipientException: Insufficient system storage. The server response was: 4.5.3 Too many recipients
Thus far, we haven't been able to figure out why this is happening. Any ideas are appreciated.
The email code uses System.Net.Mail namespace - .Net framework 4.0.
We pass in the username and password for the NetworkCredential.
public void Send(string from, string[] to, string[] cc, string[] bcc, string subject, string body, string[] attachmentArr, Boolean isBodyHtml, string smtpServerName, int port = 25, bool enableSsl = true, string userName = null, string password = null, string domain = null, int timeoutMilliSec = 100000)
{
MailMessage objEmail = new MailMessage();
try
{
foreach (string toItem in to)
{
objEmail.To.Add(toItem);
}
if (cc != null)
{
foreach (string toItem in cc)
{
objEmail.CC.Add(toItem);
}
}
if (bcc != null)
{
foreach (string toItem in bcc)
{
objEmail.Bcc.Add(toItem);
}
}
objEmail.From = new MailAddress(from);
objEmail.Subject = subject;
objEmail.Body = body;
objEmail.IsBodyHtml = isBodyHtml;
objEmail.Priority = MailPriority.High;
if (attachmentArr != null)
{
foreach (String s1 in attachmentArr)
{
objEmail.Attachments.Add(new Attachment(s1));
}
}
using (SmtpClient smtp = new SmtpClient(smtpServerName))
{
if (string.IsNullOrEmpty(userName) == false && string.IsNullOrEmpty(password) == false)
{
NetworkCredential credential = (string.IsNullOrEmpty(domain)) ? new NetworkCredential(userName, password) : new NetworkCredential(userName, password, domain);
smtp.Credentials = credential;
}
smtp.Timeout = timeoutMilliSec;
smtp.Port = port;
smtp.EnableSsl = enableSsl;
smtp.Send(objEmail);
}
}
catch (Exception ex)
{
throw ex;
}
finally
{
if (attachmentArr != null && objEmail.Attachments != null)
{
foreach (Attachment a1 in objEmail.Attachments)
{
a1.Dispose();
}
}
}
}
We finally found what was going on - Email throttling.
Office365 has a Throttling limit of 30 messages per minute for SMTP client submission https://technet.microsoft.com/en-us/library/dn554323%28v=exchg.150%29.aspx#summary
The solution was to send less than 30 messages per minute. I think it is affected by other messages (sent by Outlook) showing up to be sent by the server too. We pushed ours down to almost a five second delay between messages. We have not seen the error reoccur since.

Existing posts keep on re-added into jTable with newer post

Here are my codes :
public void submitReply(ActionEvent e) {
String replyBy = userName;
String reply = jTextArea_reply.getText();
if (reply.equals("")) {
JOptionPane.showMessageDialog(null, "Comment cannot leave blank");
} else {
eForumTopics comment = new eForumTopics(replyBy, reply);
if (comment.createComment() == true) {
JOptionPane
.showMessageDialog(null,
"Reply submitreted successfully. You will be redirect to main page.");
SetUpJTableComment();
public void SetUpJTableComment() {
// Get jTable model
DefaultTableModel tableModel1 = (DefaultTableModel) jTableComment
.getModel();
// Store column data into Array (3 columns)
String[] data = new String[3];
// Set Up Database Source
db.setUp("IT Innovation Project");
String sql = "Select reply_content,reply_by from forumReplies WHERE reply_topic = "
+ topicId + "";
ResultSet resultSet = null;
// Call readRequest to get the result
resultSet = db.readRequest(sql);
try {
while (resultSet.next()) {
data[0] = resultSet.getString("reply_content");
data[1] = resultSet.getString("reply_by");
// Add data to table model
tableModel1.addRow(data);
}
resultSet.close();
} catch (Exception e) {
System.out.println(e);
}
// add tablemodel to jtable
}
The problem is whenever users post a new reply, the existing posts will be re-added together. I try to do like only the newer reply from the comment box will be added into the jTable instead of keep on re-add the existing posts with newer reply. What am I supposed to use? A for loop? Thanks in advance.
The correct way to delete the content of DefaultTableModel is
model.setRowCount(0);
vs. the evil way mentioned in the comment (won't repeat it here ;-) which violates two rules
never change the underlying datastructure of a model under its feet
never call any of the model's fireXX from code outside the model
If doing the latter seems to help, it's a waring signal: you either violated the former or your model implementation is incorrect

How do you get the DataContext of a LINQ to SQL Entity?

Currently this is what I have:
public partial class LinqToSqlEntity {
public IQueryable<AnotherLinqToSqlEntity> AnotherLinqToSqlEntities {
using(DataContext context = new DataContext) {
return context.AnotherLinqToSqlEntities.Where(item => item.Property == SOME_VALUE);
}
}
}
Is there a way to get the DataContext of this so that I would not need to create a new DataContext?
Sorry, that is not possible. An entity or querable in that case keeps no direct reference of the context.
You can achieve that using the reflection by figuring out if PropertyChanging event was hooked up, but consider this a hack and maybe you can avoid using it with better design.
Our use case of this is on detach_EntityName delegate where we change the default Linq behaviour of only deleting the foreign key of a record (setting it to null), with the actual delete from DB.
public static DataContext GetDataContextFromEntityObject(object entity)
{
// Use a reflection to get the invocaiton list.
var o = (PropertyChangingEventHandler)entity.GetType().GetField("PropertyChanging", BindingFlags.Instance | BindingFlags.NonPublic).GetValue(entity);
var o = GetFieldValue(entity, "PropertyChanging");
if (o == null) return null;
var invocationList = o.GetInvocationList();
if (invocationList != null)
{
// DataContext changes are tracked through StandardChangeTracker
object changeTracker = (from i in invocationList where i.Target.GetType().FullName == "System.Data.Linq.ChangeTracker+StandardChangeTracker" select i.Target).FirstOrDefault();
if (changeTracker != null)
{
object services = GetFieldValue(changeTracker, "services");
return (DataContext)GetFieldValue(services, "context");
}
}
return null;
}
private static object GetFieldValue(object instance, string propertyName)
{
return instance.GetType().GetField(propertyName, BindingFlags.Instance | BindingFlags.NonPublic).GetValue(instance);
}

How to modify linqtosql entityref objects in handcoded MVC model?

I am trying to set up my own mvc model rather than letting the environment create one via the graphic designer tool. I had hoped that this would make it easier to keep separate repositories for parts of the model space but so far it has caused me nothing but grief.
The first problem I ran into was that the entityref classes had to be updated via a selectlist control in the view. I managed to get that to work by adding an interal ID field to every entityref much like designer.cs would do. However, it has made the model class quite a bit more complex as the code below demonstrates.
Unfortunately, I now run into a problem when I want to explicitly update some of the entities in the controller. If I manually set the ID field, the update is just dropped, if I change the entity I get an exception while saving.
My model
[Table(Name = "dbo.Jobs")]
public class Job {
[Column(IsPrimaryKey = true, IsDbGenerated = true, AutoSync = AutoSync.OnInsert)]
public int JobID { get; set; }
internal string _CompanyID; // string for legacy reasons
[Column(Storage = "_CompanyID")]
public string CompanyID{
get { return _CompanyID}
set {
if ((_CompanyID != value)) {
if (_MittlerOrg.HasLoadedOrAssignedValue) {
throw new System.Data.Linq.ForeignKeyReferenceAlreadyHasValueException();
}
_CompanyID = value;
}
}
}
internal EntityRef<Company> _Company;
[Association(Storage = "_Company", ThisKey = "CompanyID", OtherKey = "CompanyID", IsForeignKey = true)]
public Company Company {
get { return _Company.Entity; }
set {
Organization previousValue = this._Company.Entity;
if ((previousValue != value) || (_Company.HasLoadedOrAssignedValue == false)) {
if ((previousValue != null)) {
_Company.Entity = null;
}
_Company.Entity = value;
if (value != null) {
_CompanyID = value.OrganizationID;
} else {
_CompanyID = default(string);
}
}
}
}
// The contact depends on the choice of company and should be set
// inside an action method once the company is determined.
internal string _ContactID;
[Column(Storage = "_ContactID")]
public string ContactID {
get { return _ContactID; }
set {
if ((_ContactID != value)) {
if (_Contact.HasLoadedOrAssignedValue) {
throw new System.Data.Linq.ForeignKeyReferenceAlreadyHasValueException();
}
_ContactID = value;
}
}
}
internal EntityRef<User> _Contact;
[Association(Storage = "_Contact", ThisKey = "ContactID", OtherKey = "UserID", IsForeignKey = true)]
public User Contact {
get { return _Contact.Entity; }
set {
User previousValue = this._Contact.Entity;
if ((previousValue != value) || (_Contact.HasLoadedOrAssignedValue == false)) {
if ((previousValue != null)) {
_Contact.Entity = null;
}
_Contact.Entity = value;
if (value != null) {
_ContactID = value.UserID;
} else {
_ContactID = default(string);
}
}
}
}
}
The edit function that causes problems is here. If I step though it in the debugger I see that fi.ContactID gets updated but not committed to the DB.
[HttpPost]
public ActionResult Edit(int id, FormCollection collection) {
var user = userrep.FetchByLogin(User.Identity.Name);
var job = jobrep.FetchByID(id);
try {
var oldvalue = job.CompanyID;
UpdateModel(job, "job");
if (oldvalue != job.CompanyID) {
if (job.CompanyID != null) {
job.ContactID = orgrep.FetchByID(job.CompanyID).DefaultContactID;
} else {
job.ContactID = default(string);
}
}
firep.Save();
return RedirectToAction("Index");
} catch (Exception e) {
}
}
Any idea how to get those pesky entityrefs to behave? I searched up and down the internet but all model layer examples seem to cover the simplest relationships only. Should I just chuck the model completely in favor of managing my references manually though id fields.
Cheers,
Duffy
Update: I never got this piece of code to work robustly so I ended up switching back to letting visual studio generate the DataContext via the drag and drop graphical designer.
I still struggle a bit with fixing the names on the relationship links after an update of the db schema (I carefully name all relationships in the db but the designer tool seems to ignore those names) but since I discovered that the db.designer.cs file can be opened in an xml editor rather than with the GUI, the job got a lot easier.