示例#1
0
class CASAuthProvider(AuthProvider):
    """Provides authentication using CAS

    The type name to instantiate this provider is *cas*.
    """
    def __init__(self, *args, **kwargs):
        super(CASAuthProvider, self).__init__(*args, **kwargs)
        self.settings.setdefault('callback_uri',
                                 '/cas_auth/{}'.format(self.name))
        if not self.settings.get('cas_url_base'):
            raise MultipassException(
                "`cas_url_base` must be specified in the provider settings")
        self.cas_client = CASClient(self.settings['cas_url_base'],
                                    auth_prefix='')
        self.cas_endpoint = '_flaskmultipass_cas_' + self.name
        current_app.add_url_rule(self.settings['callback_uri'],
                                 self.cas_endpoint,
                                 self._authorize_callback,
                                 methods=('GET', 'POST'))

    @property
    def cas_callback_url(self):
        return request.url_root + self.settings['callback_uri']

    def initiate_external_login(self):
        cas_login_url = self.cas_client.get_login_url(
            service_url=self.cas_callback_url)
        return redirect(cas_login_url)

    def process_logout(self, return_url):
        cas_logout_url = self.cas_client.get_logout_url(
            service_url=self.cas_callback_url)
        return redirect(cas_logout_url)

    def _make_auth_info(self, resp):
        return AuthInfo(self, token=resp[self.settings['token_field']])

    @login_view
    def _authorize_callback(self):
        ticket = request.args.get('ticket')

        if not ticket:
            raise AuthenticationFailed('ticket is not provided')

        cas_response = self.cas_client.perform_service_validate(
            ticket=ticket,
            service_url=self.cas_callback_url,
        )

        if cas_response and cas_response.success:
            auth_info = cas_response.attributes
            auth_info['_username'] = cas_response.user
            return self.multipass.handle_auth_success(
                AuthInfo(self, **auth_info))

        raise AuthenticationFailed("CAS result: Access denied")
示例#2
0
    def get(self, request, *args):
        # 统一身份认证登录
        ticket = request.GET.get('ticket')
        cas_url = 'https://passport.ustc.edu.cn'
        app_login_url = 'http://home.ustc.edu.cn/~via'
        cas_client = CASClient(cas_url, auth_prefix='')
        if ticket:
            try:
                cas_response = cas_client.perform_service_validate(
                    ticket=ticket,
                    service_url=app_login_url,
                )
            except Exception:
                # CAS server is currently broken, try again later.
                return Response('CAS server is currently broken, try again later.', status.HTTP_503_SERVICE_UNAVAILABLE)
            if cas_response and cas_response.success:
                student_id = cas_response.user
                try:
                    user = User.objects.get(student_id=student_id)
                    # request.session['username'] = user.username
                    # request.session['userid'] = user.id
                    # request.session['isadmin'] = user.is_superuser
                    login(request, user)
                except:
                    gid = cas_response.data.get('attributes', {}).get('gid')
                    username = str(gid)
                    
                    while True:
                        try:
                            user = {'username':username, 'student_id':student_id, 'password':student_id}
                            serializer = UserSerializer(data=user)
                            serializer.is_valid(True)
                            serializer.save()
                            user = User.objects.get(student_id=student_id)
                            # request.session['username'] = user.username
                            # request.session['userid'] = user.id
                            # request.session['isadmin'] = user.is_superuser
                            login(request, user)
                            break
                        except Exception:
                            # import sys
                            # exc_type, exc_obj, exc_tb = sys.exc_info()
                            # print(f"{exc_type.__name__}: {exc_obj}")
                            username = "".join(random.choices('0123456789abcdefghijklmnopqrstuvwxyz@.+-_', k=10))

                # rep = Response('OK', status.HTTP_200_OK)        # 更换为 rep = redirect('home')
                rep = redirect('http://202.38.75.113/')
                rep.set_cookie('userid', user.id)
                return rep
        cas_login_url = cas_client.get_login_url(service_url=app_login_url)
        return redirect(cas_login_url)
示例#3
0
def cas():
    """Handles the login page, logging a user in on correct authentication."""

    #CAS client init
    cas_client = CASClient(app.config['CAS_SERVER_URL'],
                           app.config['CAS_SERVICE_URL'],
                           verify_certificates=True)

    #SLO
    if request.method == 'POST' and session.get(
            'cas_ticket') is not None and 'logoutRequest' in request.form:
        #check the verify the ticket to prevent cross orign attacks
        message = cas_client.parse_logout_request(
            request.form.get('logoutRequest'))
        if message.get('session_index', None) == session.get('cas_ticket'):
            cortex.lib.user.clear_session()
            return ('', 200)

        abort(400)

    # If the user is already logged in, just redirect them to their dashboard
    if cortex.lib.user.is_logged_in():
        return redirect(url_for('dashboard'))

    ticket = request.args.get('ticket', None)
    if ticket is not None:
        try:
            cas_response = cas_client.perform_service_validate(ticket=ticket)
        except Exception:
            return root()
        if cas_response and cas_response.success:
            try:
                # keep the ticket for SLO
                session['cas_ticket'] = ticket
                return cortex.lib.user.logon_ok(
                    cas_response.attributes.get('uid'))
            except KeyError:
                # required user attributes not returned
                flash(
                    "CAS SSO authentication successful but missing required information consider using LDAP authentication",
                    'alert-warning')
                return root()

    return redirect(cas_client.get_login_url())
示例#4
0
 def test_get_login_url(self):
     cas_client = CASClient("dummy.url")
     service_url = "app.url"
     url = cas_client.get_login_url(service_url=service_url)
     self.assertEqual(url, "dummy.url/cas/login?service=app.url")
示例#5
0
 def test_get_login_url(self):
     cas_client = CASClient('https://dummy.url')
     service_url = 'https://app.url'
     url = cas_client.get_login_url(service_url=service_url)
     self.assertEqual(
         url, 'https://dummy.url/cas/login?service=https://app.url')