480 likes | 562 Vues
A few words regarding the “SQL injection” threat. Lecture 9. SQL is powerful. Whenever you create a computer system there are several security issues to handle. This is especially true when dealing with web applications sending SQL queries to an RDBM.
E N D
SQL is powerful • Whenever you create a computer system there are several security issues to handle. • This is especially true when dealing with web applications sending SQL queries to an RDBM. • The power of SQL becomes its weakness if an intruder succeeds in sending his own malicious SQL statement to our database
SQL injection • Suppose you expect a “word” (stored in variable s) that you want to find in table “words” • statement=“SELECT * FROM words WHERE word=‘“+s+”’”; • If s=“mom” then • statement=“SELECT * FROM words WHERE word=‘mom’”; • Everyone is happy. Mom too. • But if s=“anything’; DROP TABLE members;” • statement=“SELECT * FROM words WHERE word=‘anything’; DROP TABLE members;’”; • This will first do a select query of which the intruder probably don’t care much about. Then it deletes the entire members table, of which the owner cares a lot. • Not only is it possible to destroy data. It may also be possible to extract sensitive database information, and even issue operating system commands. • Google on “SQL injection”, and you will get reading that will keep you busy.
How to deal with SQL injection • We all know that administrators have a busy time with this, but what can you and I do who write control layer Servlets in a responsible way? • Data validation • Remove single apostrophes • Or replace them with double apostrophes. • Remove semi colons and double dashes (--) • “;” is a statement separator that enables us to issue several statements on one line. • “-- “ is used as a start tag for line comments in some RDBMs. • Data type control. • If you expect an integer, reject it unless it is an integer. • or reinforce data type by explicit type conversion/casting. • Validate data via your own regular expressions • Check the data length. Truncate beyond some upper limit.
Threads Lecture 9
Today we will talk about • Pros and Cons of Threads • The Thread APIs in Java • How to create, start, stop threads • Thread safety • Mutual Exclusion through the “Synchronized” construct. • Inter-thread cooperation/communication • Wait(), Notify(), notifyAll() • Thread Groups
What is a Thread? • A thread is • An abstraction of a “process activity” • An active sequence of instructions in a process • A process activity is defined by its context: • Program counter: Tells which instruction is being executed • Stack: Determines where in the program we are (e.g.: which function, what parameters)
Process • Process is an abstraction of a program • A process has its own • program counter, stack • Code, data, heap • How do processes communicate? • Shared memory, sockets, signals • Require kernel support
Threads • Threads exist within a process • Threads share • Process code, data, heap • Each thread has its own • Program counter, stack • Multiple threads may run concurrently within the same process! • How do threads communicate? • Through process memory • Is sometimes called a “lightweight process”
Process vs. Threads Process Threads Data Code Heap Data Code Heap PC PC PC PC Stack Stack Stack Stack PC = Program Counter
Independent processes accessing the same object Class Even { Private int n = 0; Public int next(){ ++n; ++n; } } • Post condition: n always even. • If two threads are invoking next() on the same object… • The result is inconsistent data
But why Use Multiple Threads • User input thread & data-processing thread • user-input has high priority • but users are slow (compared to CPUs) • so keep processing while waiting • Parallelize a chain of events • Dispatcher thread and Worker threads • Web server • One thread per user • Model independent objects in simulations • Like traffic in Frogger !!!
Thread API & Features • Thread class • Runnable interface • Timer & TimerTask classes • ThreadLocal class • synchronized keyword • wait(), notify(), notifyAll() (methods inherited from Object class) • ThreadGroup class
Multi-threaded Processing • JVM schedules processor time for each thread and dictates when they get control • You can not know or control exactly how this happens, and it will be different on different systems • Different threads might “share” objects, so you don’t know which thread will access it first. • You can schedule priorities for threads.
Making Your Own Threads • You have 2 options: • extend Thread • Fine if you’re not trying to extend anything else • You get your thread directly by instantiating your class • implement Runnable interface • More flexible, therefore usually preferred. • Your class can be a part of a class hierarchy unrelated to threads. • You get your thread by passing an instantiation of your Runnable class to the thread constructor • Either way, you deal with a Thread object.
Extending the Thread class • you must override run()with the code that this thread should execute when running • Instantiate your class • Don’t call run()Call start() to begin execution.
Implementing Runnable Interface • Do this when you want to extend some other class. • You must implement the run() method • Create a new instance of the Runnable • Pass it to the thread constructor. • new Thread( myRunnable ) • Call start (and other methods) on the thread, as before.
Thread Methods • Static • currentThread() • Accessors • getPriority() & setPriority(int) • isDaemon() & setDaemon(boolean) • isAlive() • Thread Control • start() [which calls run()] • sleep() • yield() • join() • Once a Thread has finished execution, is it dead and may not be restarted.
Thread State Diagram See also figure 5-2, page 333
Deprecated Thread methods You should not use stop(), suspend(), and resume() to control threads ! • Reason: inherently unsafe: may leave data in an inconstant state. Deprecated since 1.2, which was when they figured this out. • Instead, use flags (see next slide) ...
Alternatives to Deprecated Thread Methods • Give your Runnable class volatileboolean fields, possibly named ‘suspendFlag’ & ‘stopFlag’ • Provide setters for them, possibly named ‘setSuspend(boolean)’ and ‘stopThread()’ • Have your code check them frequently • when stopFlag is true, end the run method, leaving the data in a consistent state • when suspendFlag is true, have the Thread sleep a little bit, and then check the flag again.
Special Kinds of Threads • Daemon Threads • continuous loop running in background • listens for and handles requests • when your program has only daemon threads left running, they are terminated by the JVM and the application closes, because daemon threads normally never terminate on their own. • TimerTask Threads • you can schedule tasks to be done later • run in background threads • controlled by Timer objects • use only for short tasks
Using TimerTasks • Basics: • extend TimerTask • implement run() method • instantiate your TimerTask subclass • instantiate Timer • schedule your TimerTask with the Timer • Additional TimerTask methods: • long scheduledExecutionTime() • void cancel()
How to schedule a TimerTask in a Timer • Schedule an event to happen at a certain time, or after a certian delay: • myTimer.schedule( myTask, time ) • myTimer.schedule( myTask, delay ) • Optionally, add a period parameter for recurring events. The period specifies the time between repeat occurances • myTimer.schedule( myTask, time, period ) • myTimer.schedule( myTask, delay, period) • For tasks where the absolute timing of recurring events is important, like a clock striking on the hour, use these methods instead. If event is a little late, the others will ‘catch up’. • myTimer.scheduleAtFixedRate(myTask, time, period ) • myTimer.scheduleAtFixedRate(myTask, delay, period)
Thread safety Lecture 9
Mutual exclusion - Monitors • “Monitor” is a general concept (see figure) that is implemented via the “synchronized” framework in Java. • Monitors ensure mutual exclusion automatically so that there is no more than one thread can be executing in a monitor at any time. • Thus we can “monitor” areas of interest in the code.
Do like this Class Even { private int n = 0; public int next(){ synchronized (this) { ++n; ++n; } } } Affects a block in a method Or… Class Even { private int n = 0; public synchronized int next(){ ++n; ++n; } } Affects the whole method Early example: Synchronization solves it.
Synchronization of code blocks • syntax: • synchronized (lock_object ) [fill in statement or code block] • when to use: • If a method is long, and many threads request it, synchronizing the smallest block of code that keeps the variables consistent will reduce the chance of deadlock. • How does it work? • When a thread enters the synchronized code block, it takes hold on the ”lock_object”, and holds on to it until it exits the code block. • Only one thread can hold a lock_object at a time. • If another thread tries to enter the code block while the lock_object is occupied, the thread is halted until the lock_object is released.
Synchronization of methods • Why: to keep your variables in a consistent state • How: declare the methods that access them to be synchronized • What: JVM requires that no thread can access a method that another thread is currently in: provides a “lock” on the object (if instance method) or class (if static method)
Synchronization and Inner Classes • Suppose an inner class object has access to fields of the outer class object. • Suppose an outer class method and an inner class method is run in parallel in different threads. • This may cause inconsistent field values, and these outer class instance variables need to be protected in multithreaded programs. • Simply synchronizing the methods may not protect the outer class fields, because the inner methods will be locked with the inner class instance and the outer methods will be locked with the outer class instance. • Solution: instead of synchronizing the inner class method, synchronize its code with the enclosing object as a lock. • Synchronized (Outer.this) { … } • Now we are synchronizing the code blocks with the same locking-object, which is what we want.
Good Multi-threading Techniques • If a variable should only be accessed by one thread, make it “Thread-safe”. • If variables could be accessed by more than one thread, do one of the following: • synchronize the code that calls them • declare them volatile • Think about how your threads could interfere with each other – try to avoid deadlock! • Deadlock - Two persons trying to phone each other at the same time. Busy-tone at both ends. • Spinlock - Your big brother is always faster in reaching the candy jar. • Locks may lead to starvation • = an object will never get access to the desired resource.
Thread-Safety • Local variables are automatically thread-safe • Instance variables of an object whose methods are run by multiple threads are not safe • declare methods that access it synchronized • or declare the variable volatile • Class (a.k.a. static) variables are not thread-safe • declare methods that access it synchronized • or declare the variable volatile • or make them of type ThreadLocal or InheritableThreadLocal (see next slide)
Using ThreadLocal and InheritableThreadLocal • Good for when you want the field to be shared by multiple instances of the same class that are running in the same Thread, but not shared with instances of the class that are running on other Threads • InheritableThreadLocal allows child Threads to share the variable with parent Threads. • Methods: • Object get() • Object initialValue() • void set( Object value)
Communicating with wait() and notify() • methods inherited from Object that affect Threads: • wait() • wait(long timeout) • wait(long timeout, int timeoutAddNanos) • notify() • notifyAll() • Any object can call these, but only when the current Thread has a lock on the object. • These methods are final -- they may not be overridden.
The wait methods [Inherited from Object] • Tells the current thread to release it’s lock, chill, and let another Thread (chosen by the JVM) execute • wait() – waits until notified by another thread • wait( long timeout ) – waits for the specified number of milliseconds • wait( long timeout, int timeoutAddNanos) – waits for the specified number of milliseconds + the specified number of nanoseconds
The notify methods[Inherited from Object] • notify() - the JVM chooses one thread that has been waiting, and puts it into a runnable state. As soon as it can aquire the needed lock, it starts. • notifyAll() – the JVM places all waiting threads into a runnable state, and then chooses one to get control and execute. The others are poised, ready to go as soon as they can get the necessary lock.
When to use wait and notify • When a Thread needs to wait until a particular condition is satisfied before continuing. • Waiting for input, empty buffer, etc. • Alternative to sleep() • Typical usage: while (condition) { wait(); } • (Check the condition again when notified in case the notification was unrelated to your condition) • Use notify() when efficiency is a special concern, and all waiting threads are waiting for the same Object lock, so that any Thread the JVM chooses would be appropriate. • Use notifyAll() when Threads are waiting for different Object locks. Each thread will check it’s condition, and at least one Thread should become able to continue.
Example: wait, notifyAll public class BankAccount { private int balance = 0; private boolean isOpen = true; public synchronized boolean withdraw( int amount) throws InterruptedException { while (amount > balance && isOpen()) { System.out.println("Waiting for $"); wait(); } boolean result = false; if (isOpen()) { balance -= amount; result = true; } return result; } // withdraw public synchronized boolean deposit( int amount) { if (isOpen()) { balance += amount; notifyAll(); return true; } else { return false; } } // deposit public synchronized boolean isOpen() { return isOpen; } // isOpen public synchronized void close() { isOpen = false; notifyAll(); } // close } // class
Thread Grouping • Why: • you can protect one group of threads from another • A Thread can only modify threads in the same group (or child group) • you can perform operations (setPriority or interrupt) on all the threads in the group at once, instead of having to iterate through • What: • stores a collection of Threads that have a special security relationship to each other • each ThreadGroup can also have child ThreadGroups, allowing for a ThreadGroup heirarchy
ThreadGroup class • methods include: • int activeCount() & int activeGroupCount() • int enumerate(Thread[] list, boolean recurse] ) • int enumerate(ThreadGroup[] list, boolean recurse] ) • int getMaxPriority() & void setMaxPriority() • String getName() & ThreadGroup getParent() [set by constructor] • boolean isDaemon() & void setDaemon(boolean daemon) • list() [prints debugging info to System.out] • interrupt()
ThreadGroups, continued • Threads can only modify each other (like setting their priorities) if they are in the same ThreadGroup • By default, Threads go in the same ThreadGroup as the Thread that created it. • To override this default behavior, pass a ThreadGroup to the Thread constructor. • A Thread’s ThreadGroup cannot be changed.
Threads & Anonymous Inner Classes: FileWatcher Exercise • Complete the following class definition. • Use an anonymous inner class that extends Thread. It should print a line to System.out when the file is created, or immediately if it already exists. • You can not add code anywhere other than inside the watchFile method definition. import java.io.File; public class FileWatcher { public void watchFile( final String fileName ) { //fill this in, please. } }
FileWatcher Solution import java.io.File; public class FileWatcher { public void watchFile(final String fileName) { Thread t; t = new Thread() { File f = new File(fileName); public void run () { while (!f.exists()) { try { sleep(50); } catch (InterruptedException e) { e.printStackTrace(); } } System.out.println(fileName+" exists!"); } }; t.start(); } }
Threads & Anonymous Inner Classes: Timer Exercise import java.util.*; public class Alarm { private static Timer timer = new Timer(); public static void stopAlarms() { timer.cancel(); } public static void setRecurringAlarm(final String msg, long interval) { /* Fill this in, please. After the interval specified by the parameter, the msg should be printed to System.out. After another interval, print the alarm msg again. Repeat...*/ } public static void main(String[] args) { /* Fill this in, please. Set up two alarms, one that prints “one second has passed” every second, and one that prints “five seconds have passed” every five seconds. Let them both go for twenty seconds, then stop them. After they have stopped, print “alarms stopped!”, and then the program should exit normally. */ } }
Timer Exercise Solution import java.util.*; public class Alarm { private static Timer timer = new Timer(); public static void stopAlarms() { timer.cancel(); } public static void setRecurringAlarm(final String msg, long interval) { TimerTask task = new TimerTask() { public void run() { System.out.println(msg); } }; timer.scheduleAtFixedRate(task, interval, interval); } public static void main(String[] args) { long oneSecond = 1000, fiveSeconds = 5000, twentySeconds = 20000; Alarm.setRecurringAlarm("one second has passed", oneSecond); Alarm.setRecurringAlarm("five seconds have passed", fiveSeconds); TimerTask task = new TimerTask() { public void run() { Alarm.stopAlarms(); System.out.println("alarms stopped!"); } }; timer.schedule(task, twentySeconds); } }