[ 
https://issues.apache.org/jira/browse/SHIRO-647?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel
 ]

Stanisław Barański updated SHIRO-647:
-------------------------------------
    Description: 
Hello. 
I'm trying to implement one role at a time scenario. 

It this case first I'm signing user with 
{code:java}
//Kotlin
val token = UsernamePasswordToken(credentials.name, credentials.password) 
SecurityUtils.getSubject().login(token) {code}
then, when the user select role I create session: 
{code:java}
val sessionId = SecurityUtils.getSubject().session.id as String 
val mySession = MySession(sessionId, selectedRoleId) {code}
then when the user wants to execute request I restore Subject from this 
sessionId 
{code:java}
val subject = Subject.Builder() 
       .sessionId(mySession.sessionId) 
       .buildSubject() {code}
and everything goes fine, in the doGetAuthorizationInfo method I'm able to 
identify the Subject from principalCollection since there is his id (eg. 2). 
{code:java}
fun doGetAuthorizationInfo(principals: PrincipalCollection) { 
    val subjectId : Long = principals.fromRealm(name).iterator().next() as Long 
    ... {code}
but the problem is when I want to be aware of selected role in the 
doGetAuthorizationInfo method. I tried to pass another principal with selected 
roleId but 
{code:java}
val rolePrincipal = RolePrincipal(mySession.roleId) 
val principals = SimplePrincipalCollection(listOf(rolePrincipal, mySession.id), 
realm.name) 

val subject = Subject.Builder() 
      .principals(principals) 
      .sessionId(mySession.id) 
      .buildSubject() {code}
then the session is not being resolved and in the doGetAuthorizationInfo 
method, I'm only getting raw mySession.id(eg. 
"36fa4f4a-d55e-47df-8170-13bcdf6f2aa6") instead of mine subjectId(eg. 2). 

In other words 
               
{noformat}
 .principals(principals) {noformat}
and 
               
{noformat}
 .sessionId(mySession.id) {noformat}
seems to not work together, the .principals is blocking .sessionId from being 
resolved to subjectId. 

 

 

EDIT:

It's not elegant but I found workaround:

 

 
{code:java}
val subject = Subject.Builder()
        .sessionId(mySession.id)
        .buildSubject()

// Recreate Subject with additional rolePrincipal
val rolePrincipal = RolePrincipal(mySession.roleId)
val principals = listOf(subject.principal, rolePrincipal)

val subjectContext = DefaultSubjectContext()
subjectContext.session = subject.session
subjectContext.isAuthenticated = subject.isAuthenticated
subjectContext.principals = SimplePrincipalCollection(principals, realm.name)
val subjectRecreated = DefaultSubjectFactory().createSubject(subjectContext)

if (!subjectRecreated.isAuthenticated)
    throw AuthorizationException("Restored session is not authenticated")

subjectRecreated.checkPermission("user:read:*")
{code}
 

 and then in my doGethAuthorizationInfo I'm easly getting both subjectId and 
selected roleId

 
{code:java}
override fun doGetAuthorizationInfo(principals: PrincipalCollection){
    var subjectId: Long = -1L
    var roleId: Long = -1L

    for (principal in principals.fromRealm(name).iterator())
        when (principal) {
            is Long -> subjectId = principal
            is RolePrincipal -> roleId = principal.roleId
        }{code}
But I'm sure there is better approach to do so.

 

  was:
Hello. 
I'm trying to implement one role at a time scenario. 

It this case first I'm signing user with 


{code:java}
                val token = UsernamePasswordToken(credentials.name, 
credentials.password) 
                SecurityUtils.getSubject().login(token) {code}


then, when the user select role I create session: 


{code:java}
                val sessionId = SecurityUtils.getSubject().session.id as String 
                val mySession = MySession(sessionId, selectedRoleId) {code}


then when the user wants to execute request I restore Subject from this 
sessionId 


{code:java}
                val subject = Subject.Builder() 
                        .sessionId(mySession.sessionId) 
                        .buildSubject() {code}


and everything goes fine, in the doGetAuthorizationInfo method I'm able to 
identify the Subject from principalCollection since there is his id (eg. 2). 


{code:java}
fun doGetAuthorizationInfo(principals: PrincipalCollection) { 
    val subjectId : Long = principals.fromRealm(name).iterator().next() as Long 
    ... {code}

but the problem is when I want to be aware of selected role in the 
doGetAuthorizationInfo method. I tried to pass another principal with selected 
roleId but 


{code:java}
val rolePrincipal = RolePrincipal(mySession.roleId) 
val principals = SimplePrincipalCollection(listOf(rolePrincipal, mySession.id), 
realm.name) 

val subject = Subject.Builder() 
                     .principals(principals) 
                     .sessionId(mySession.id) 
                        .buildSubject() {code}

then the session is not being resolved and in the doGetAuthorizationInfo 
method, I'm only getting raw mySession.id(eg. 
"36fa4f4a-d55e-47df-8170-13bcdf6f2aa6") instead of mine subjectId(eg. 2). 

In other words 
               
{noformat}
 .principals(principals) {noformat}

and 
               
{noformat}
 .sessionId(mySession.id) {noformat}


seems to not work together, the .principals is blocking .sessionId from being 
resolved to subjectId. 

 


> SubjectBuilder doesn't fill principals when principals and sessionId is 
> specified
> ---------------------------------------------------------------------------------
>
>                 Key: SHIRO-647
>                 URL: https://issues.apache.org/jira/browse/SHIRO-647
>             Project: Shiro
>          Issue Type: Bug
>          Components: Authentication (log-in)
>    Affects Versions: 1.3.2
>            Reporter: Stanisław Barański
>            Priority: Minor
>
> Hello. 
> I'm trying to implement one role at a time scenario. 
> It this case first I'm signing user with 
> {code:java}
> //Kotlin
> val token = UsernamePasswordToken(credentials.name, credentials.password) 
> SecurityUtils.getSubject().login(token) {code}
> then, when the user select role I create session: 
> {code:java}
> val sessionId = SecurityUtils.getSubject().session.id as String 
> val mySession = MySession(sessionId, selectedRoleId) {code}
> then when the user wants to execute request I restore Subject from this 
> sessionId 
> {code:java}
> val subject = Subject.Builder() 
>        .sessionId(mySession.sessionId) 
>        .buildSubject() {code}
> and everything goes fine, in the doGetAuthorizationInfo method I'm able to 
> identify the Subject from principalCollection since there is his id (eg. 2). 
> {code:java}
> fun doGetAuthorizationInfo(principals: PrincipalCollection) { 
>     val subjectId : Long = principals.fromRealm(name).iterator().next() as 
> Long 
>     ... {code}
> but the problem is when I want to be aware of selected role in the 
> doGetAuthorizationInfo method. I tried to pass another principal with 
> selected roleId but 
> {code:java}
> val rolePrincipal = RolePrincipal(mySession.roleId) 
> val principals = SimplePrincipalCollection(listOf(rolePrincipal, 
> mySession.id), realm.name) 
> val subject = Subject.Builder() 
>       .principals(principals) 
>       .sessionId(mySession.id) 
>       .buildSubject() {code}
> then the session is not being resolved and in the doGetAuthorizationInfo 
> method, I'm only getting raw mySession.id(eg. 
> "36fa4f4a-d55e-47df-8170-13bcdf6f2aa6") instead of mine subjectId(eg. 2). 
> In other words 
>                
> {noformat}
>  .principals(principals) {noformat}
> and 
>                
> {noformat}
>  .sessionId(mySession.id) {noformat}
> seems to not work together, the .principals is blocking .sessionId from being 
> resolved to subjectId. 
>  
>  
> EDIT:
> It's not elegant but I found workaround:
>  
>  
> {code:java}
> val subject = Subject.Builder()
>         .sessionId(mySession.id)
>         .buildSubject()
> // Recreate Subject with additional rolePrincipal
> val rolePrincipal = RolePrincipal(mySession.roleId)
> val principals = listOf(subject.principal, rolePrincipal)
> val subjectContext = DefaultSubjectContext()
> subjectContext.session = subject.session
> subjectContext.isAuthenticated = subject.isAuthenticated
> subjectContext.principals = SimplePrincipalCollection(principals, realm.name)
> val subjectRecreated = DefaultSubjectFactory().createSubject(subjectContext)
> if (!subjectRecreated.isAuthenticated)
>     throw AuthorizationException("Restored session is not authenticated")
> subjectRecreated.checkPermission("user:read:*")
> {code}
>  
>  and then in my doGethAuthorizationInfo I'm easly getting both subjectId and 
> selected roleId
>  
> {code:java}
> override fun doGetAuthorizationInfo(principals: PrincipalCollection){
>     var subjectId: Long = -1L
>     var roleId: Long = -1L
>     for (principal in principals.fromRealm(name).iterator())
>         when (principal) {
>             is Long -> subjectId = principal
>             is RolePrincipal -> roleId = principal.roleId
>         }{code}
> But I'm sure there is better approach to do so.
>  



--
This message was sent by Atlassian JIRA
(v7.6.3#76005)

Reply via email to