# Java Passwortverwaltung



## aziz (25. Mrz 2017)

Hallo, ich lerne gerade neu java und komme bei einer Aufgabe nicht weiter, ich weiß nicht wie ich das machen soll, dass der erste Buchstabe ein Großbuchstaben sein muss und ich im Passwort gleichzeitig ein Sonderzeichen erfolgt, die Aufgabe lautet im allgemeinen: 
Implementieren Sie zunächst ein Programm, das untersucht, ob ein eingegebener Text einem vorgegebenen Benutzernamen entspricht.
Erweitern Sie das bestehende Programm so, dass der Benutzer zur Eingabe eines Passwortes aufgefordert wird.
Dieses Passwort wird nur akzeptiert, wenn es mind. 8 Zeichen lang ist. 
Diese Anforderung legt eine Minimalanforderungen an die Sicherheit des Passwortes fest, die dem Benutzer durch die Ausgabe des Sicherheitslevels mit nur einem * angezeigt wird (Sicherheitslevel: *).
Erweitern Sie Ihr Programm um folgende Eigenschaften:
Der Benutzer soll die Option haben, den Sicherheitslevel auf level 2 oder 3 zu erhöhen (Anzeige -> Sicherheitslevel ** oder ***).
Sicherheitslevel 2 ist erreicht, wenn im Passwort ein Zeichen ein Großbuchstabe und ein Zeichen eine Zahl ist.
Sicherheitslevel 3 ist erreicht, wenn im Passwort zusätzlich das erste Zeichen ein Großbuchstabe und ein Zeichen ein Sonderzeichen ist.
Erst dann soll das Passwort vom Programm mit einer entsprechenden Ausgabe akzeptiert werden. 

Mein Ansatz wäre: 

   public static void main(String[] args) {

       Scanner eingabe = new Scanner(System.in);
       System.out.println("Bitte geben sie einen Benutzernamen ein ");
       String Benutzername = eingabe.next();  
       Scanner eingabe1 = new Scanner(System.in);
       System.out.println("Bitte geben sie ein Passwort ein ");
       String passwort = eingabe1.next();
       String sonderzeichen = "[^!§$%&/()?=]+";
       String level2 = "[A-Z1-9]+";

       if(passwort.length()>=8)
       {   
           System.out.println("Sicherheitslevel1:* ");
       }else{
           System.out.println("");
       }

       if(!passwort.matches(sonderzeichen)){
           System.out.println("Sicherheitsleve3:***");

       }else{
           System.out.println("");
       }

       if(passwort.matches(level2)){
           System.out.println("Sicherheitslevel2: **");
       }else{
           System.out.println("Großbuchstaben erfordert");
       }





   }

}


----------



## Tobse (25. Mrz 2017)

Zwei Dinge:

Erstens: 





aziz hat gesagt.:


> ich weiß nicht wie ich das machen soll, dass der erste Buchstabe ein Großbuchstaben sein muss und ich im Passwort gleichzeitig ein Sonderzeichen erfolgt


Lies diesen Satz bitte nochmal aufmerksam. Ergibt der Sinn für dich? Für mich auch nicht  Formuliere das bitte nochmal, damit wir wissen, wo dein Problem genau liegt. Aktuell kann ich dir nämlich nicht wirklich helfen, weil ich nicht weiss, wo es klemmt :/

Zweitens: Java-Code bitte immer in den BB-Tags dafür [JAVA ] CODE HIER [/JAVA ] (ohne die Leerzeichen)


----------



## aziz (25. Mrz 2017)

Tut mir Leid, ich bin neu hier wusste nicht wo der java code hin muss. Meine frage wäre wie ich Sicherheitslevel 2 und Sicherheitslevel 3 erreichen könnte. Also: 
Sicherheitslevel 2 ist erreicht, wenn im Passwort ein Zeichen ein Großbuchstabe und ein Zeichen eine Zahl ist.
Sicherheitslevel 3 ist erreicht, wenn im Passwort zusätzlich das erste Zeichen ein Großbuchstabe und ein Zeichen ein Sonderzeichen ist. Ich habe es mit regex und mit isUpperCase versucht leider kommt nicht das gewünschte ergebnis raus und jetzt stehe ich auf den schlauch


----------



## Tobse (25. Mrz 2017)

Mit RegularExpressions geht das schon, ist aber meiner Meinung nach mit Kanonen auf Spatzen geschossen.

Mal der Reihe nach:

Level 3 kann nicht erreicht sein, wenn Level 2 nicht erreicht ist. Ergo brauchst du auf die Bedingungen für Level 3 auch gar nicht erst prüfen, wenn die für Level 2 fehlschlagen.


```
int level = 1;

// Bedingungen für Level 2
boolean hasUppercaseLetter = /* kommt noch */;
boolean hasDigit = /* kommt noch */;

if (hasUppercaseLetter && hasDigit) {
  level = 2;
}

// Bedingungen für Level 3
boolean firstCharacterIsUpperCase = /* kommt noch */;
boolean hasSpecialCharacter = /* kommt noch */;

if (level == 2 && firstCharacterIsUpperCase && hasSpecialCharacter) {
  level = 3;
}
```

Jetzt zu den einzelnen Bedingungen:

Bei welchen bist du dir unsicher / welche funktionieren nicht? Ich könnte dir jetzt den Code für alle geben, das hätte aber keinen Lerneffekt für dich


----------



## aziz (25. Mrz 2017)

Ich danke dir für deine Hilfe, ich hatte das mir Regex gemacht, leider kam immer der boolische ausdruck false raus und kam da bei level 2 schon nicht weiter, ich habe mit der methode isUpperCase um bei jedem wert des Indexes herauszubekommen ob großbuchstabe rauskommt, aber leider hat das nicht geklappt, obwohl im String großbuchstaben vorhanden waren, hat die Methode leider nicht gewirkt und dann habe ich alles gelöscht und mein derzeitiger stand ist ja schon im forum gepostet worden


----------



## Tobse (25. Mrz 2017)

Weißt du schon was Schleifen und Arrays sind? Falls ja: ein String (= das Passwort) ist ein Array von _char_s, über welches du iterieren kannst und mit dem du Bedingungen für jeden einzelnen Buchstaben prüfen kannst. Versuche damit mal, _hasUppercaseCharacter_, _hasDigit _und _hasSpecialCharacter _lösen.

Siehe dafür:

Character.isUpperCase(char)
Character.isDigit(char)
Character.isLetter(char)
Ein _char_ ist dann ein Sonderzeichen, wenn er weder eine Ziffer noch ein Buchstabe ist

Bezüglich _firstCharacterIsUpperCase_:
Das hängt von der Position im Passwort ab. Es bezieht sich ganz klar auf das erste Zeichen. Ein String ist ein Array von _char_s. Weisst du, wie du da an das erste Element kommst?


----------



## aziz (26. Mrz 2017)

Nochmals vielen Dank für die Unterstützung, ich habe das zweite Sicherheitslevel erreicht. Habe den Code unten reinkopiert - falls verbesserungsvorschläge da sind nehme ich sie gerne an -. Jetzt müsste ich das nur noch mit dem firstCharacterIsUpperCase hinbekommen und das mit dem Sonderzeichen. Ich habe ja meinen String zu einem CharArray umgewandelt, deswegen kann ich über dem CharArray nicht auf den Index des ersten Buchstabens kommen.  Leider weiß ich nicht wie ich an das erste element komme und wie ich das dann mit der Methode Character.isUpperCase in verbindung setze .... 






```
public class Aufgabe4 {

   public static void main(String[] args) {
      
       Scanner eingabe = new Scanner(System.in);
       System.out.println("Bitte geben sie einen Benutzernamen ein ");
       String Benutzername = eingabe.next(); 
       Scanner eingabe1 = new Scanner(System.in);
       System.out.println("Bitte geben sie ein Passwort ein ");
       String passwort = eingabe1.next();
      
       char []x =  passwort.toCharArray();
       int level;

       // Sicherheitslevel 1
       boolean hasMorethan8Letter;
      
       // Sicherheitslevel 2 bedingung
       boolean hasUppercaseLetter;
       boolean hasDigit;
      
       // Sicherheitslevel 3 bedingung
       boolean firstCharacterIsUpperCase;
       boolean hasSpecialCharacter;
      
       //-----------------------//
       hasMorethan8Letter = false;
       hasUppercaseLetter = false;
       hasDigit = false;
       firstCharacterIsUpperCase=false;
       hasSpecialCharacter =false;
      
       if(x.length>=8){
           hasMorethan8Letter = true;
           level = 1;
       }          
      
      
       for(int i = 0; i<x.length;i++){
           if(Character.isUpperCase(x)){
               hasUppercaseLetter = true;
           }
           if(Character.isDigit(x)){
               hasDigit=true;
           }
               level = 2;
       }
      
       if(hasUppercaseLetter && hasDigit){
           System.out.println("Level 2");
       }
      
  
       }
           }
```


----------



## aziz (26. Mrz 2017)

Ich glaube ich habe es geschafft. Vielleicht geht es etwas übersichtlicher, aber es erfüllt seinen zweck. Ich bedanke mich recht herzlich für deine hilfe, hast mir wirklich sehr geholfen. Unten der vollständige code:

```
Scanner eingabe = new Scanner(System.in);
       System.out.println("Bitte geben sie einen Benutzernamen ein ");
       String Benutzername = eingabe.next(); 
       Scanner eingabe1 = new Scanner(System.in);
       System.out.println("Bitte geben sie ein Passwort ein ");
       String passwort = eingabe1.next();
      
       char []x =  passwort.toCharArray();
       int level;

       // Sicherheitslevel 1
       boolean hasMorethan8Letter;
      
       // Sicherheitslevel 2 bedingung
       boolean hasUppercaseLetter;
       boolean hasDigit;
      
       // Sicherheitslevel 3 bedingung
       boolean firstCharacterIsUpperCase;
       boolean hasSpecialCharacter;
      
       //-----------------------//
       hasMorethan8Letter = false;
       hasUppercaseLetter = false;
       hasDigit = false;
       firstCharacterIsUpperCase=false;
       hasSpecialCharacter =false;
      
       if(x.length>=8){
           hasMorethan8Letter = true;
           level = 1;
       }          
       if(hasMorethan8Letter){
           System.out.println("Level 1");
       }
      
      
       for(int i = 0; i<x.length;i++){
           if(Character.isUpperCase(x[I])){
               hasUppercaseLetter = true;
           }
           if(Character.isDigit(x[I])){
               hasDigit=true;
           }
               level = 2;
       
       }
       
       if(hasUppercaseLetter && hasDigit){
           System.out.println("Level 2");
       }
       
       for (int j = 0; j<x.length;j++){
           if(Character.isUpperCase(x[0])){
               firstCharacterIsUpperCase=true;
               
           if(!Character.isLetterOrDigit(x[j])){
               hasSpecialCharacter =true;
               level =3;
               }
           }
       }
       if(hasUppercaseLetter && hasDigit && firstCharacterIsUpperCase && hasSpecialCharacter){
           System.out.println("level 3");
       }
       
   
       }
           }
```
[/I][/I]


----------



## Tobse (26. Mrz 2017)

Dieser Code kompiliert nicht einmal! Hat man dir denn gezeigt, wie man Java-Code kompiliert?
Falls nein: Schande über deinen Lehrer. Google hilft dir weiter und der Java-Compiler allein zeigt dir 6 Fehler, die auf jeden Fall raus müssen.
Falls ja: ändere sofort deine Arbeitsweise. Code, den man nicht mal kompiliert hat, irgendjemandem zu geben, ist unverschämt und macht einen schlechten Eindruck. Das ist vergleichbar damit, ein Auto zu verkaufen, dessen Motor man vor dem Verkauf nicht ein einziges mal gestartet hat. Der Compiler ist dein Freund, nicht dein Feind. Er ist dazu da, Fehler zu finden.

Da der Code nicht kompiliert sage ich jetzt nur was zu dem Code, den ich mir schon angesehen hatte, bis ich gemerkt habe, dass der Code nicht kompilieren _kann_.

Zuerst die Ästhetik: gib der Variable X einen besseren Namen. x ist nicht aussagekräftig. Besser wäre z.B. _passwordChars._
Leider muss man die Code-Tags groß schreiben ([CODE=JAVA ] anstatt [code=JAVA ]) damit sie funktionieren :/

Jetzt zur Logik: die ist an vielen Stellen sehr fehlerhaft.

Deine If-Statements sind sehr problematisch:


```
if(x.length>=8){
    hasMorethan8Letter = true;
    level = 1;
}
if(hasMorethan8Letter){
    System.out.println("Level 1");
}
```


Das ist schwer nachzuvollziehen. Um herauszufinden, welche Kriterien für Level 1 notwendig sind, Muss ich beide Ifs lesen.
Was ist, wenn für Level 1 eine weitere Bedingung hinzukommt? Wieviel Code musst du dann ändern?
Die Variable _hasMorethan8Letter_ ist falsch benannt. Sie kann auch true sein, wenn es _genau 8_ sind, der Name suggeriert aber, dass es _mehr als 8_ sein müssen. _hasMoreThan7Letters _oder _hasAtLeast8Letters _sind bessere Namen.

Ich hätte den Code so geschrieben:


```
if (x.length >= 8) {
  hasAtLeast8Letters= true;
}

if (hasAtLeast8Letters) {
  level = 1;
  System.out.println("Level 1");
}
```

Hier ist der Code, der die einzelnen Bedingungen prüft, klar von dem Code getrennt, der festlegt, welche Bedingungen welches Level ausmachen. Das verbessert die zwei Problemaspekte:


wenn für Level 1 eine Bedingung hinzukommt, musst du den Code, der die bereits vorhandenen Bedingungen prüft, nicht mehr ändern. Eine neue Variable und ein zusätzliches If reichen aus. Je weniger man Code verändert, desto weniger wahrscheinlich macht man ihn kaputt (=baut Bugs ein) 
Man kann den unteren Teil des Codes lesen und versteht die Logik. An dem Unteren If kann man sehen, dass man für Level 1 mindestens 8 Zeichen braucht. Das obere If muss man sich dafür garnicht durchlesen. Das macht den Code leichter und schneller zu verstehen.


----------



## aziz (26. Mrz 2017)

Ich danke dir nochmals für deine Ratschläge, ist das aber alles was man da verbessern könnte? Zum kompilieren: Unser Professor in der Uni geht jetzt bald in Rente und er erklärt uns nichts mehr, wir sollen einfach nur die theorie auf einer VM  lesen und anwenden können, jeder ist auf sich selbst gestellt, quasi ins kalte wasser geschmissen, leider und das programmieren habe ich mir bis hierher alles selbst beigebracht, deswegen ist keine ordentliche Struktur da. Hat das kompilieren etwas mit der Konsole bzw. der Eingabeaufforderung zutun? Ich programmiere unter Eclipse und Eclipse zeigt mir keine fehler an ...


----------



## mrBrown (26. Mrz 2017)

Tobse hat gesagt.:


> Falls nein: Schande über deinen Lehrer. Google hilft dir weiter und der Java-Compiler allein zeigt dir 6 Fehler, die auf jeden Fall raus müssen.





aziz hat gesagt.:


> Ich programmiere unter Eclipse und Eclipse zeigt mir keine fehler an



uU ist da was durch die Formatierung kaputt gegangen, `[i]` wird im nicht-Code-Text ja zu kursiv...[/i]


----------



## Tobse (26. Mrz 2017)

mrBrown hat gesagt.:


> uU ist da was durch die Formatierung kaputt gegangen, `[I]` wird im nicht-Code-Text ja zu kursiv...[/I]


Oh.... da hast du recht; das erklärt auch, warum der Code bei mir nicht kompiliert.

@aziz Sorry, Poste ihn bitte nochmal in Code Tags mit Großbuchstaben [CODE ]...[/CODE ]

Da gibt es noch mehr dinge zu verbessern; habe aber an der Stelle erstmal aufgehört, wo semantische Fehler drin waren (wegen der Formatierung). Man kann das Thema noch ganz stark erweitern; aber dafür sind dann aber tiefgehende OOP-Kenntnisse notwendig (die du, wie ich vermute, noch nicht hast).


----------



## aziz (26. Mrz 2017)

```
public static void main(String[] args) {
       
       Scanner eingabe = new Scanner(System.in);
       System.out.println("Bitte geben sie einen Benutzernamen ein ");
       String Benutzername = eingabe.next();  
       Scanner eingabe1 = new Scanner(System.in);
       System.out.println("Bitte geben sie ein Passwort ein ");
       String passwort = eingabe1.next();
       
       char []x =  passwort.toCharArray();
       int level;

       // Sicherheitslevel 1
       boolean hasMorethan8Letter;
       
       // Sicherheitslevel 2 bedingung
       boolean hasUppercaseLetter;
       boolean hasDigit;
       
       // Sicherheitslevel 3 bedingung
       boolean firstCharacterIsUpperCase;
       boolean hasSpecialCharacter;
       
       //-----------------------//
       hasMorethan8Letter = false;
       hasUppercaseLetter = false;
       hasDigit = false;
       firstCharacterIsUpperCase=false;
       hasSpecialCharacter =false;
       
       if(x.length>=8){
           hasMorethan8Letter = true;
           level = 1;
       }           
       if(hasMorethan8Letter){
           System.out.println("Level 1 **");
       }
       
       
       for(int i = 0; i<x.length;i++){
           if(Character.isUpperCase(x[i])){
               hasUppercaseLetter = true;
           }
           if(Character.isDigit(x[i])){
               hasDigit=true;
           }
               level = 2;
       
       }
       
       if(hasUppercaseLetter && hasDigit){
           System.out.println("Level 2 **");
       }
       
       for (int j = 0; j<x.length;j++){
           if(Character.isUpperCase(x[0])){ // an der stelle 0 prüfen ob es ein großbuchstabe ist
               firstCharacterIsUpperCase=true;
               
           if(!Character.isLetterOrDigit(x[j])){
               hasSpecialCharacter =true;
               level =3;
               }
           }
       }
       if(hasUppercaseLetter && hasDigit && firstCharacterIsUpperCase && hasSpecialCharacter){
           System.out.println("level 3 ***");
       }
       
   
       }
           }
```


----------



## aziz (26. Mrz 2017)

vielleicht kann man ja den code ja irgendwie objekt orientiert umschreiben, wäre eine gute übung.


----------



## Tobse (26. Mrz 2017)

Ja, das kann man. Aber das macht erst Sinn, wenn diese Version des Codes auf einem guten Stand ist. Und das ist sie noch nicht 

Weitere Verbesserungen:


Nimm die Variable level raus; du benutzt sie nirgends. Sie wird falsch gesetzt und lenkt nur ab.
In der letzten schleife ist ein Fehler: hinter dem ersten If steht ein {, dass da nichts verloren hat. Das gesamte If gehört aus der Schleife raus, weil es mit der Schleife nichts zu tun hat.


```
if(Character.isUpperCase(x[0])){ // an der stelle 0 prüfen ob es ein großbuchstabe ist
  firstCharacterIsUpperCase=true;
}

for (int j = 0; j<x.length;j++) {
  if(!Character.isLetterOrDigit(x[j])) {
    hasSpecialCharacter =true;
  }
}
```

Setze das alles mal um. Eine OO-Lösung macht mmn. hier noch keinen Sinn; du solltest zuerst die Basics beherrschen. Wenn du dich trotzdem dran versuchen möchtest:

In einer OO-Lösung würde ich folgende Klassen und Interfaces benutzen:


Enum PasswordGrade { LEVEL0, LEVEL1, LEVEl2, LEVEL3 }
Interface PasswordGrader
Interface PasswordCriterion
Klasse CriterionPasswordGrader


----------



## aziz (27. Mrz 2017)

Ich danke dir vielmals für die Verbesserungsvorschläge des Codes, ich habe sie auch alle jetzt umgesetzt. Die Klassen und Interfaces die du mir für die oop Lösung gesendet hast, sagen mir tatsächlich bis jetzt noch nichts, bin aber motiviert und werde das lernen.


----------



## mrBrown (27. Mrz 2017)

aziz hat gesagt.:


> Die Klassen und Interfaces die du mir für die oop Lösung gesendet hast, sagen mir tatsächlich bis jetzt noch nichts, bin aber motiviert und werde das lernen.


Die Klassen gibts auch nicht, die müsste man dafür noch schreiben


----------



## Joose (27. Mrz 2017)

Tobse hat gesagt.:


> Leider muss man die Code-Tags groß schreiben ([CODE=JAVA ] anstatt [code=JAVA ]) damit sie funktionieren :/





Tobse hat gesagt.:


> Sorry, Poste ihn bitte nochmal in Code Tags mit Großbuchstaben [CODE ]...[/CODE ]



Zur Information: Man muss die Code-Tags nicht groß schreiben. [code=java] .... java code hier ....[/code] funktioniert auch wunderbar.
@Tobse um jemanden auf die Code-Tags hinzuweisen kannst du die Plain-Tags verwenden 
[plain][code=java] .... java code hier .... [/code][/plain] wird zu -> [code=java] .... java code hier .... [/code]


----------



## Tobse (27. Mrz 2017)

Joose hat gesagt.:


> Zur Information: Man muss die Code-Tags nicht groß schreiben. [code=java] .... java code hier ....[/code] funktioniert auch wunderbar.
> @Tobse um jemanden auf die Code-Tags hinzuweisen kannst du die Plain-Tags verwenden
> [plain][code=java] .... java code hier .... [/code][/plain] wird zu -> [code=java] .... java code hier .... [/code]


Man lernt nie aus!


----------

